<commit_before>#include "core/argparse.h"

#include "utils.h"
#include "core/enumtostring.h"

using namespace euphoria::core::argparse;

namespace
{
    Arguments
    MakeArguments(const std::vector<std::string>& args)
    {
        return Arguments{ "path/to/app", args };
    }

    struct Message
    {
        bool error;
        std::string text;

        Message(bool e, const std::string& t)
            : error(e)
            , text(t)
        {
        }
    };

    template<typename T>
    std::ostream&
    operator<<(std::ostream& o, const std::vector<T>& m)
    {
        o << "[";
        bool first = true;
        for(const auto& t: m)
        {
            if(first) {first = false;}
            else { o << ", "; }
            o << t;
        }
        o << "]";
        return o;
    }

    std::ostream&
    operator<<(std::ostream& o, const Message& m)
    {
        o << (m.error?"ERR":"INF");
        o << " " << m.text;
        return o;
    }

    struct TestPrinter : public Printer
    {
        std::vector<Message> messages;

        void
        PrintError(const std::string& line) override
        {
            messages.emplace_back(true, line);
        }

        void
        PrintInfo(const std::string& line) override
        {
            messages.emplace_back(false, line);
        }
    };

    enum class Animal
    {
        Cat, Dog, Bird
    };

    std::ostream&
    operator<<(std::ostream& o, const Animal& m)
    {
        o << euphoria::core::EnumToString(m);
        return o;
    }

}

TEST_CASE("argparse", "[argparse]")
{
    auto parser = Parser{};
    auto output = std::make_shared<TestPrinter>();
    parser.printer = output;

    SECTION("default")
    {
        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
        }
    }

    SECTION("void function")
    {
        std::string var = "default";
        parser.AddVoidFunction("-f", [&]
        {
            var = "called";
        });

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(var == "default");
        }

        SECTION("function called")
        {
            const auto res = parser.Parse(MakeArguments({ "-f" }));
            CHECK(res == ParseResult::Ok);
            CHECK(var == "called");
        }
    }

    SECTION("optional int")
    {
        int value = 0;
        parser.Add("-f", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == 0);
        }

        SECTION("parse 42")
        {
            const auto res = parser.Parse(MakeArguments({ "-f", "42" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == 42);
        }
    }

    SECTION("optional string")
    {
        std::string value = "default";
        parser.Add("-f", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == "default");
        }

        SECTION("parse 42")
        {
            const auto res = parser.Parse(MakeArguments({ "-f", "dog" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == "dog");
        }
    }

    SECTION("optional enum")
    {
        Animal value = Animal::Dog;
        parser.Add("-f", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Dog);
        }

        SECTION("parse cat")
        {
            const auto res = parser.Parse(MakeArguments({ "-f", "cat" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Cat);
        }
    }

    SECTION("multi optional names")
    {
        Animal value = Animal::Dog;
        parser.Add("-a, --animal", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Dog);
        }

        SECTION("short name")
        {
            const auto res = parser.Parse(MakeArguments({ "-a", "cat" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Cat);
        }

        SECTION("long name")
        {
            const auto res = parser.Parse(MakeArguments({ "--animal", "bird" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Bird);
        }
    }

    SECTION("positional string")
    {
        std::string value = "default";
        parser.Add("f", &value);

        SECTION("positional missing = error")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Error);
            CHECK(value == "default");
        }

        SECTION("parse 42")
        {
            const auto res = parser.Parse(MakeArguments({ "dog" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == "dog");
        }
    }

    SECTION("subparser")
    {
        std::string a = "default";
        std::string b = "default";

        auto sub = parser.AddSubParsers();

        sub->Add("a", [&](SubParser* parser)
        {
            std::string a_value = "dog";
            parser->Add("-s", &a_value);

            return parser->OnComplete([&]
            {
                a = a_value;
                return ParseResult::Ok;
            });
        });

        sub->Add("b", [&](SubParser*)
        {
            b = "bird";
            return ParseResult::Ok;
        });

        SECTION("empty subparser = error")
        {
            const auto res = parser.Parse(MakeArguments({}));
            INFO(output->messages);
            CHECK(res == ParseResult::Error);
            CHECK(a == "default");
            CHECK(b == "default");
        }

        SECTION("call a")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "a"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(a == "dog");
            CHECK(b == "default");
        }

        SECTION("call a with arg")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "a", "-s", "cat"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(a == "cat");
            CHECK(b == "default");
        }

        SECTION("call b")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "b"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(a == "default");
            CHECK(b == "bird");
        }
    }

    SECTION("non greedy subparser/script like")
    {
        auto sub = parser.AddSubParsers();
        std::string data;
        sub->Add("add", [&](SubParser* sub)
        {
            std::string what;
            sub->parser_style = SubParserStyle::Fallback;
            sub->Add("what", &what);
            return sub->OnComplete([&]
            {
                data += what;
                return ParseResult::Ok;
            });
        });
        sub->Add("double", [&](SubParser* sub)
        {
            return sub->OnComplete([&]
            {
                data += data;
                return ParseResult::Ok;
            });
        });

        SECTION("once")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "add", "dog"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(data == "dog");
        }

        SECTION("twice")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "add", "cat",
                    "double"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(data == "catcat");
        }
    }

    SECTION("non root root")
    {
        auto sub = parser.AddSubParsers();
        std::string data;
        sub->Add("pretty", [&](SubParser* pretty)
        {
            pretty->AddSubParsers()->Add("please", [&](SubParser* please)
            {
                please->parser_style = SubParserStyle::Fallback;
                auto sub = please->AddSubParsers();
                sub->Add("add", [&](SubParser* sub)
                {
                    std::string what;
                    sub->Add("what", &what);
                    return sub->OnComplete([&]
                    {
                        data += what;
                        return ParseResult::Ok;
                    });
                });
                sub->Add("double", [&](SubParser* sub)
                {
                    return sub->OnComplete([&]
                    {
                        data += data;
                        return ParseResult::Ok;
                    });
                });
                return please->OnComplete([]{return ParseResult::Ok;});
            });
            return pretty->OnComplete([]{return ParseResult::Ok;});
        });

        SECTION("once")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "pretty", "please", "add", "dog"
                })
            );
            CHECK(res == ParseResult::Ok);
            CHECK(data == "dog");
        }

        SECTION("twice")
        {
            const auto arguments =
                MakeArguments
                ({
                    "pretty", "please", "add", "cat",
                    "please", "double"
                });
            const auto res = parser.Parse
            (
                arguments
            );
            INFO(output->messages);
            INFO(arguments);
            REQUIRE(data == "catcat");
            CHECK(res == ParseResult::Ok);
        }
    }
}
<commit_msg>wip: added error tests<commit_after>#include "core/argparse.h"

#include "utils.h"
#include "core/enumtostring.h"

using namespace euphoria::core::argparse;

namespace
{
    Arguments
    MakeArguments(const std::vector<std::string>& args)
    {
        return Arguments{ "path/to/app", args };
    }

    struct Message
    {
        bool error;
        std::string text;

        Message(bool e, const std::string& t)
            : error(e)
            , text(t)
        {
        }
    };

    template<typename T>
    std::ostream&
    operator<<(std::ostream& o, const std::vector<T>& m)
    {
        o << "[";
        bool first = true;
        for(const auto& t: m)
        {
            if(first) {first = false;}
            else { o << ", "; }
            o << t;
        }
        o << "]";
        return o;
    }

    std::ostream&
    operator<<(std::ostream& o, const Message& m)
    {
        o << (m.error?"ERR":"INF");
        o << " " << m.text;
        return o;
    }

    struct TestPrinter : public Printer
    {
        std::vector<Message> messages;

        void
        PrintError(const std::string& line) override
        {
            messages.emplace_back(true, line);
        }

        void
        PrintInfo(const std::string& line) override
        {
            messages.emplace_back(false, line);
        }
    };

    enum class Animal
    {
        Cat, Dog, Bird
    };

    std::ostream&
    operator<<(std::ostream& o, const Animal& m)
    {
        o << euphoria::core::EnumToString(m);
        return o;
    }

}

TEST_CASE("argparse", "[argparse]")
{
    auto parser = Parser{};
    auto output = std::make_shared<TestPrinter>();
    parser.printer = output;

    SECTION("default")
    {
        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
        }
    }

    SECTION("void function")
    {
        std::string var = "default";
        parser.AddVoidFunction("-f", [&]
        {
            var = "called";
        });

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(var == "default");
        }

        SECTION("function called")
        {
            const auto res = parser.Parse(MakeArguments({ "-f" }));
            CHECK(res == ParseResult::Ok);
            CHECK(var == "called");
        }
    }

    SECTION("optional int")
    {
        int value = 0;
        parser.Add("-f", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == 0);
        }

        SECTION("parse 42")
        {
            const auto res = parser.Parse(MakeArguments({ "-f", "42" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == 42);
        }
    }

    SECTION("optional string")
    {
        std::string value = "default";
        parser.Add("-f", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == "default");
        }

        SECTION("parse 42")
        {
            const auto res = parser.Parse(MakeArguments({ "-f", "dog" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == "dog");
        }
    }

    SECTION("optional enum")
    {
        Animal value = Animal::Dog;
        parser.Add("-f", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Dog);
        }

        SECTION("parse cat")
        {
            const auto res = parser.Parse(MakeArguments({ "-f", "cat" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Cat);
        }
    }

    SECTION("multi optional names")
    {
        Animal value = Animal::Dog;
        parser.Add("-a, --animal", &value);

        SECTION("empty parser is ok")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Dog);
        }

        SECTION("short name")
        {
            const auto res = parser.Parse(MakeArguments({ "-a", "cat" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Cat);
        }

        SECTION("long name")
        {
            const auto res = parser.Parse(MakeArguments({ "--animal", "bird" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == Animal::Bird);
        }
    }

    SECTION("positional string")
    {
        std::string value = "default";
        parser.Add("f", &value);

        SECTION("positional missing = error")
        {
            const auto res = parser.Parse(MakeArguments({}));
            CHECK(res == ParseResult::Error);
            CHECK(value == "default");
        }

        SECTION("parse 42")
        {
            const auto res = parser.Parse(MakeArguments({ "dog" }));
            CHECK(res == ParseResult::Ok);
            CHECK(value == "dog");
        }
    }

    SECTION("subparser")
    {
        std::string a = "default";
        std::string b = "default";

        auto sub = parser.AddSubParsers();

        sub->Add("a", [&](SubParser* parser)
        {
            std::string a_value = "dog";
            parser->Add("-s", &a_value);

            return parser->OnComplete([&]
            {
                a = a_value;
                return ParseResult::Ok;
            });
        });

        sub->Add("b", [&](SubParser*)
        {
            b = "bird";
            return ParseResult::Ok;
        });

        SECTION("empty subparser = error")
        {
            const auto res = parser.Parse(MakeArguments({}));
            INFO(output->messages);
            CHECK(res == ParseResult::Error);
            CHECK(a == "default");
            CHECK(b == "default");
        }

        SECTION("call a")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "a"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(a == "dog");
            CHECK(b == "default");
        }

        SECTION("call a with arg")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "a", "-s", "cat"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(a == "cat");
            CHECK(b == "default");
        }

        SECTION("call b")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "b"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(a == "default");
            CHECK(b == "bird");
        }
    }

    SECTION("non greedy subparser/script like")
    {
        auto sub = parser.AddSubParsers();
        std::string data;
        sub->Add("add", [&](SubParser* sub)
        {
            std::string what;
            sub->parser_style = SubParserStyle::Fallback;
            sub->Add("what", &what);
            return sub->OnComplete([&]
            {
                data += what;
                return ParseResult::Ok;
            });
        });
        sub->Add("double", [&](SubParser* sub)
        {
            return sub->OnComplete([&]
            {
                data += data;
                return ParseResult::Ok;
            });
        });

        SECTION("once")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "add", "dog"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(data == "dog");
        }

        SECTION("twice")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "add", "cat",
                    "double"
                })
            );
            INFO(output->messages);
            CHECK(res == ParseResult::Ok);
            CHECK(data == "catcat");
        }
    }

    SECTION("non root root")
    {
        auto sub = parser.AddSubParsers();
        std::string data;
        sub->Add("pretty", [&](SubParser* pretty)
        {
            pretty->AddSubParsers()->Add("please", [&](SubParser* please)
            {
                please->parser_style = SubParserStyle::Fallback;
                auto sub = please->AddSubParsers();
                sub->Add("add", [&](SubParser* sub)
                {
                    std::string what;
                    sub->Add("what", &what);
                    return sub->OnComplete([&]
                    {
                        data += what;
                        return ParseResult::Ok;
                    });
                });
                sub->Add("double", [&](SubParser* sub)
                {
                    return sub->OnComplete([&]
                    {
                        data += data;
                        return ParseResult::Ok;
                    });
                });
                return please->OnComplete([]{return ParseResult::Ok;});
            });
            return pretty->OnComplete([]{return ParseResult::Ok;});
        });

        SECTION("once")
        {
            const auto res = parser.Parse
            (
                MakeArguments
                ({
                    "pretty", "please", "add", "dog"
                })
            );
            CHECK(res == ParseResult::Ok);
            CHECK(data == "dog");
        }

        SECTION("twice")
        {
            const auto arguments =
                MakeArguments
                ({
                    "pretty", "please", "add", "cat",
                    "please", "double"
                });
            const auto res = parser.Parse
            (
                arguments
            );
            INFO(output->messages);
            INFO(arguments);
            REQUIRE(data == "catcat");
            CHECK(res == ParseResult::Ok);
        }
    }
}

TEST_CASE("argparse_error", "[argparse]")
{
    auto parser = Parser{};
    auto output = std::make_shared<TestPrinter>();
    parser.printer = output;

    SECTION("default")
    {
        SECTION("one positional")
        {
            const auto res = parser.Parse(MakeArguments({"dog"}));
            CHECK(res == ParseResult::Error);
        }
        SECTION("many positionals")
        {
            const auto res = parser.Parse(MakeArguments({"cat", "dog"}));
            CHECK(res == ParseResult::Error);
        }
        SECTION("positional 1 dash")
        {
            const auto res = parser.Parse(MakeArguments({"-o"}));
            CHECK(res == ParseResult::Error);
        }
        SECTION("positional 2 dashes")
        {
            const auto res = parser.Parse(MakeArguments({"--make-cool"}));
            CHECK(res == ParseResult::Error);
        }
    }
}
<|endoftext|>


<commit_before>#ifndef GRAPHICS_TEXTURE_HPP
#define GRAPHICS_TEXTURE_HPP

#include "OE/Graphics/API/Buffer.hpp"

namespace OrbitEngine { namespace Graphics {
	enum TextureFormat {
		R8 = 0,
		RGB,
		R16,
		RG8,
		RG32F,
		RGB8,
		RGB32F,
		RGB16F,
		RGBA,
		RGBA8,
		RGBA32F,
		SRC_ALPHA,
		LUMINANCE_ALPHA,
		DEPTH,
		DEPTH_STENCIL
	};

	enum TextureFilter {
		ANISOTROPIC = 0,
		LINEAR,
		NEAREST
	};

	enum TextureWrap {
		REPEAT = 0,
		MIRROR_REPEAT,
		CLAMP,
		CLAMP_TO_EDGE,
		CLAMP_TO_BORDER
	};

	enum TextureDataType {
		UNSIGNED_INT,
		UNSIGNED_BYTE,
		FLOAT
	};

	enum TextureDimension {
		TEXTURE1D,
		TEXTURE2D,
		TEXTURE2DARRAY,
		TEXTURE3D,
		CUBEMAP
	};

	struct TextureFormatProperties {
		TextureFormat format = RGB;
		TextureDataType dataType = UNSIGNED_BYTE;
	};

	struct TextureSampleProperties {
		TextureWrap wrap = CLAMP_TO_EDGE;
		TextureFilter filter = ANISOTROPIC;
		bool mipmapping = true;
	};

	struct TextureProperties {
		TextureFormatProperties formatProperties;
		TextureSampleProperties sampleProperties;
		TextureDimension dimension = TEXTURE2D;
		BufferMode textureBufferMode = DYNAMIC;
		unsigned short width = 16, height = 16;
	};

	class Texture {
	public:
		virtual ~Texture();

		static Texture* Create(TextureProperties& properties, std::vector<void*> data);
		static Texture* Create(TextureProperties& properties, void* data = 0);
		static Texture* Load(std::vector<std::string> files, TextureSampleProperties& sampleProperties);
		static Texture* Load(std::string file, TextureSampleProperties& sampleProperties);
		static Texture* Load(std::vector<std::string> files);
		static Texture* Load(std::string file);

		virtual void bind(unsigned int slot) = 0;
		virtual void setData(void* data, unsigned int offset = 0) = 0;
		virtual void copy(Texture* source) = 0;

		static void Unbind(const unsigned int slot);

		inline unsigned int getMipmapLevelsCount() { return m_Properties.sampleProperties.mipmapping ? m_MipLevels : 1; };

		TextureProperties getProperties() const { return m_Properties; }

		static void* LoadImageData(const std::string& file, TextureFormatProperties& formatProperties, unsigned int& width, unsigned int& height);
		static unsigned int CalculateMipLevelsCount(unsigned int width, unsigned int height);
		static unsigned int BPPFromFormat(TextureFormat format);
	protected:
		Texture(TextureProperties properties);

		TextureProperties m_Properties;
		unsigned int m_MipLevels = 1;

	private:
		static bool s_FreeImageInitialized;
	};
} }

#endif<commit_msg>mipmap generation disabled by default<commit_after>#ifndef GRAPHICS_TEXTURE_HPP
#define GRAPHICS_TEXTURE_HPP

#include "OE/Graphics/API/Buffer.hpp"

namespace OrbitEngine { namespace Graphics {
	enum TextureFormat {
		R8 = 0,
		RGB,
		R16,
		RG8,
		RG32F,
		RGB8,
		RGB32F,
		RGB16F,
		RGBA,
		RGBA8,
		RGBA32F,
		SRC_ALPHA,
		LUMINANCE_ALPHA,
		DEPTH,
		DEPTH_STENCIL
	};

	enum TextureFilter {
		ANISOTROPIC = 0,
		LINEAR,
		NEAREST
	};

	enum TextureWrap {
		REPEAT = 0,
		MIRROR_REPEAT,
		CLAMP,
		CLAMP_TO_EDGE,
		CLAMP_TO_BORDER
	};

	enum TextureDataType {
		UNSIGNED_INT,
		UNSIGNED_BYTE,
		FLOAT
	};

	enum TextureDimension {
		TEXTURE1D,
		TEXTURE2D,
		TEXTURE2DARRAY,
		TEXTURE3D,
		CUBEMAP
	};

	struct TextureFormatProperties {
		TextureFormat format = RGB;
		TextureDataType dataType = UNSIGNED_BYTE;
	};

	struct TextureSampleProperties {
		TextureWrap wrap = CLAMP_TO_EDGE;
		TextureFilter filter = ANISOTROPIC;
		bool mipmapping = false;
	};

	struct TextureProperties {
		TextureFormatProperties formatProperties;
		TextureSampleProperties sampleProperties;
		TextureDimension dimension = TEXTURE2D;
		BufferMode textureBufferMode = DYNAMIC;
		unsigned short width = 16, height = 16;
	};

	class Texture {
	public:
		virtual ~Texture();

		static Texture* Create(TextureProperties& properties, std::vector<void*> data);
		static Texture* Create(TextureProperties& properties, void* data = 0);
		static Texture* Load(std::vector<std::string> files, TextureSampleProperties& sampleProperties);
		static Texture* Load(std::string file, TextureSampleProperties& sampleProperties);
		static Texture* Load(std::vector<std::string> files);
		static Texture* Load(std::string file);

		virtual void bind(unsigned int slot) = 0;
		virtual void setData(void* data, unsigned int offset = 0) = 0;
		virtual void copy(Texture* source) = 0;

		static void Unbind(const unsigned int slot);

		inline unsigned int getMipmapLevelsCount() { return m_Properties.sampleProperties.mipmapping ? m_MipLevels : 1; };

		TextureProperties getProperties() const { return m_Properties; }

		static void* LoadImageData(const std::string& file, TextureFormatProperties& formatProperties, unsigned int& width, unsigned int& height);
		static unsigned int CalculateMipLevelsCount(unsigned int width, unsigned int height);
		static unsigned int BPPFromFormat(TextureFormat format);
	protected:
		Texture(TextureProperties properties);

		TextureProperties m_Properties;
		unsigned int m_MipLevels = 1;

	private:
		static bool s_FreeImageInitialized;
	};
} }

#endif<|endoftext|>


<commit_before>#include "TriggerEditor.hpp"

#include <array>
#include <algorithm>
#include <Engine/Component/Trigger.hpp>
#include <Engine/Component/Script.hpp>
#include <Engine/Component/Shape.hpp>
#include <Engine/Component/RigidBody.hpp>
#include <Engine/Manager/Managers.hpp>
#include <Engine/Manager/TriggerManager.hpp>
#include <Engine/Manager/ResourceManager.hpp>
#include <Engine/Trigger/TriggerRepeat.hpp>
#include <Engine/Hymn.hpp>
#include <Engine/Entity/Entity.hpp>
#include <Engine/Script/ScriptFile.hpp>
#include <imgui.h>

// This is necessary to use std::string in ImGui::Combo(). Taken from https://github.com/ocornut/imgui/issues/1180
namespace ImGui {
    static auto vector_getter = [](void* vec, int idx, const char** out_text) {
        auto& vector = *static_cast<std::vector<std::string>*>(vec);
        if (idx < 0 || idx >= static_cast<int>(vector.size())) { return false; }
        *out_text = vector.at(idx).c_str();
        return true;
    };

    bool Combo(const char* label, int* currIndex, std::vector<std::string>& values) {
        if (values.empty()) { return false; }
        return Combo(label, currIndex, vector_getter,
            static_cast<void*>(&values), values.size());
    }
}

namespace GUI {
    void TriggerEditor::Open() {
        ImGui::SetNextWindowPosCenter();
        ImGui::OpenPopup("trigger-edit");
    }

    void TriggerEditor::Show(Component::Trigger& comp) {
        if (ImGui::BeginPopupModal("trigger-edit", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_ShowBorders)) {
            if (ImGui::RadioButton("Properties", selectedTab == PROPERTIES))
                selectedTab = PROPERTIES;

            ImGui::SameLine();

            if (ImGui::RadioButton("Subjects", selectedTab == SUBJECTS))
                selectedTab = SUBJECTS;

            ImGui::SameLine();

            if (ImGui::Button("Close"))
                ImGui::CloseCurrentPopup();

            ImGui::Separator();

            // Working under the assumption that the internal trigger
            // is set and is indeed a repeat trigger.
            auto repeat = Managers().triggerManager->GetTriggerRepeat(comp);
            assert(repeat);
            repeat->SetOwningEntity(comp.entity);

            switch (selectedTab) {
                case PROPERTIES: {
                    std::array<char, 100> name;
                    float delay = repeat->GetDelay();
                    float cooldown = repeat->GetCooldown();
                    int charges = repeat->GetTriggerCharges();
                    int startActive = repeat->GetStartActive();

                    memcpy(name.data(), repeat->GetName().c_str(), std::min(repeat->GetName().size(), name.size()));
                    name[std::min(repeat->GetName().size(), name.size() - 1)] = '\0';

                    // NAME
                    if (ImGui::InputText("Name", name.data(), name.size()))
                        repeat->SetName(name.data());

                    // DELAY
                    if (ImGui::InputFloat("Delay", &delay, 0.1f, 1.0f, 1)) {

                        if (delay < 0.0f)
                            delay = 0.0f;

                        repeat->SetDelay(delay);
                    }
                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("Time in seconds to delay.\nHold button to increase speed.");

                    // COOLDOWN
                    if (ImGui::InputFloat("Cooldown", &cooldown, 0.1f, 1.0f, 1)) {

                        if (cooldown < 0.0f)
                            cooldown = 0.0f;

                        repeat->SetCooldown(cooldown);
                    }

                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("Time in seconds to cooldown.\nHold button to increase speed.");

                    // CHARGES
                    if (ImGui::InputInt("Charges", &charges)) {

                        if (charges < 0)
                            charges = 0;

                        repeat->SetTriggerCharges(charges);
                    }
                    ImGui::SameLine();

                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("How many times a trigger can execute before automatically going inactive.\n0 = INFINITE.\nHold button to increase speed.");

                    // START ACTIVE
                    ImGui::Text("Start active? ");

                    ImGui::SameLine();

                    if (ImGui::RadioButton("Yes", &startActive, 1))
                        repeat->SetStartActive(true);

                    ImGui::SameLine();

                    if (ImGui::RadioButton("No", &startActive, 0))
                        repeat->SetStartActive(false);

                    break;
                }
                case SUBJECTS: {

                    // Hardcoded single event for demonstration purposes
                    if (ImGui::Button("New event", ImVec2(100, 25))) {
                        triggerEvent::EventStruct newStruct;
                        repeat->GetEventVector()->push_back(newStruct);
                    }

                    ImGui::NewLine();
                    ImGui::Columns(4);

                    ImGui::Text("Event");
                    ImGui::NextColumn();
                    ImGui::Text("Shape");
                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("When this shape collide with trigger volume the trigger will be executed.");

                    ImGui::NextColumn();
                    ImGui::Text("Target entity");
                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("Entity to gather script from.");

                    ImGui::NextColumn();
                    ImGui::Text("Script method");
                    ImGui::Separator();

                    for (int i = 0; i < repeat->GetEventVector()->size(); i++) {
                        ImGui::Columns(4);

                        std::array<const char*, 3> events = {
                            "OnEnter",
                            "OnRetain",
                            "OnLeave",
                        };

                        std::string labelEvent = "Type ";
                        labelEvent.append(std::to_string(i));
                        std::string labelShape = "Shape ";
                        labelShape.append(std::to_string(i));
                        std::string labelTarget = "Entity ";
                        labelTarget.append(std::to_string(i));
                        std::string labelScript = "Script ";
                        labelScript.append(std::to_string(i));

                        // Event type
                        int eventType = repeat->GetEventVector()->at(i).m_eventID;

                        if (ImGui::Combo(labelEvent.c_str(), &eventType, events.data(), events.size())) {
                            repeat->GetEventVector()->at(i).m_eventID = eventType;
                            repeat->GetEventVector()->at(i).check[0] = true;
                        }

                        // Subject
                        ImGui::NextColumn();
                        int shapeID = repeat->GetEventVector()->at(i).m_shapeID;
                        std::vector<std::string> entityWithShape;
                        for (int i = 0; i < Hymn().world.GetEntities().size(); i++) {
                            if (Hymn().world.GetEntities().at(i)->GetComponent<Component::RigidBody>() != nullptr)
                                entityWithShape.push_back(Hymn().world.GetEntities().at(i)->name);
                        }

                        if (ImGui::Combo(labelShape.c_str(), &shapeID, entityWithShape)) {
                            repeat->GetEventVector()->at(i).m_shapeID = shapeID;

                            for (int j = 0; j < Hymn().world.GetEntities().size(); j++) {
                                if (Hymn().world.GetEntities().at(j)->name == entityWithShape.at(shapeID)) {
                                    repeat->GetCollidedEntity()->push_back(Hymn().world.GetEntities().at(j));
                                    repeat->GetEventVector()->at(i).check[1] = true;
                                }
                            }
                        }

                        // Entity target
                        ImGui::NextColumn();
                        int targetID = repeat->GetEventVector()->at(i).m_targetID;
                        std::vector<std::string> entityName;

                        for (int i = 0; i < Hymn().world.GetEntities().size(); i++) {
                            if (Hymn().world.GetEntities().at(i)->GetComponent<Component::Script>() != nullptr && Hymn().world.GetEntities().at(i)->name != comp.entity->name)
                                entityName.push_back(Hymn().world.GetEntities().at(i)->name);
                        }

                        if (ImGui::Combo(labelTarget.c_str(), &targetID, entityName)) {
                            repeat->GetEventVector()->at(i).m_targetID = targetID;

                            for (int j = 0; j < Hymn().world.GetEntities().size(); j++) {

                                if (Hymn().world.GetEntities().at(j)->name == entityName.at(targetID)) {
                                    repeat->GetTargetEntity()->push_back(Hymn().world.GetEntities().at(j));
                                    repeat->GetEventVector()->at(i).check[2] = true;
                                }
                            }
                        }

                        // Script name
                        ImGui::NextColumn();
                        int scriptID = repeat->GetEventVector()->at(i).m_scriptID;

                        std::vector<std::string> scriptVector;

                        if (!repeat->GetTargetEntity()->empty()) {
                            for (int x = 0; x < repeat->GetTargetEntity()->size(); x++) {

                                if (repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>() != nullptr && repeat->GetTargetEntity()->at(x)->name == entityName.at(targetID)) {

                                    for (int j = 0; j < repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>()->scriptFile->functionList.size(); j++) {

                                        if (std::find(scriptVector.begin(), scriptVector.end(), repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>()->scriptFile->functionList.at(j)) == scriptVector.end())
                                            scriptVector.push_back(repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>()->scriptFile->functionList.at(j));
                                    }
                                }
                            }
                        }

                        if (!scriptVector.empty()) {
                            if (ImGui::Combo(labelScript.c_str(), &scriptID, scriptVector)) {
                                repeat->GetEventVector()->at(i).m_scriptID = scriptID;
                                repeat->GetTargetFunction()->push_back(scriptVector.at(scriptID));
                                repeat->GetEventVector()->at(i).check[3] = true;
                            }
                        }

                        ImGui::Separator();
                    }
                    break;
                }
            }

            ImGui::EndPopup();
        }
    }
}
<commit_msg>Fix signed/unsigned comparisons<commit_after>#include "TriggerEditor.hpp"

#include <array>
#include <algorithm>
#include <Engine/Component/Trigger.hpp>
#include <Engine/Component/Script.hpp>
#include <Engine/Component/Shape.hpp>
#include <Engine/Component/RigidBody.hpp>
#include <Engine/Manager/Managers.hpp>
#include <Engine/Manager/TriggerManager.hpp>
#include <Engine/Manager/ResourceManager.hpp>
#include <Engine/Trigger/TriggerRepeat.hpp>
#include <Engine/Hymn.hpp>
#include <Engine/Entity/Entity.hpp>
#include <Engine/Script/ScriptFile.hpp>
#include <imgui.h>

// This is necessary to use std::string in ImGui::Combo(). Taken from https://github.com/ocornut/imgui/issues/1180
namespace ImGui {
    static auto vector_getter = [](void* vec, int idx, const char** out_text) {
        auto& vector = *static_cast<std::vector<std::string>*>(vec);
        if (idx < 0 || idx >= static_cast<int>(vector.size())) { return false; }
        *out_text = vector.at(idx).c_str();
        return true;
    };

    bool Combo(const char* label, int* currIndex, std::vector<std::string>& values) {
        if (values.empty()) { return false; }
        return Combo(label, currIndex, vector_getter,
            static_cast<void*>(&values), values.size());
    }
}

namespace GUI {
    void TriggerEditor::Open() {
        ImGui::SetNextWindowPosCenter();
        ImGui::OpenPopup("trigger-edit");
    }

    void TriggerEditor::Show(Component::Trigger& comp) {
        if (ImGui::BeginPopupModal("trigger-edit", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_ShowBorders)) {
            if (ImGui::RadioButton("Properties", selectedTab == PROPERTIES))
                selectedTab = PROPERTIES;

            ImGui::SameLine();

            if (ImGui::RadioButton("Subjects", selectedTab == SUBJECTS))
                selectedTab = SUBJECTS;

            ImGui::SameLine();

            if (ImGui::Button("Close"))
                ImGui::CloseCurrentPopup();

            ImGui::Separator();

            // Working under the assumption that the internal trigger
            // is set and is indeed a repeat trigger.
            auto repeat = Managers().triggerManager->GetTriggerRepeat(comp);
            assert(repeat);
            repeat->SetOwningEntity(comp.entity);

            switch (selectedTab) {
                case PROPERTIES: {
                    std::array<char, 100> name;
                    float delay = repeat->GetDelay();
                    float cooldown = repeat->GetCooldown();
                    int charges = repeat->GetTriggerCharges();
                    int startActive = repeat->GetStartActive();

                    memcpy(name.data(), repeat->GetName().c_str(), std::min(repeat->GetName().size(), name.size()));
                    name[std::min(repeat->GetName().size(), name.size() - 1)] = '\0';

                    // NAME
                    if (ImGui::InputText("Name", name.data(), name.size()))
                        repeat->SetName(name.data());

                    // DELAY
                    if (ImGui::InputFloat("Delay", &delay, 0.1f, 1.0f, 1)) {

                        if (delay < 0.0f)
                            delay = 0.0f;

                        repeat->SetDelay(delay);
                    }
                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("Time in seconds to delay.\nHold button to increase speed.");

                    // COOLDOWN
                    if (ImGui::InputFloat("Cooldown", &cooldown, 0.1f, 1.0f, 1)) {

                        if (cooldown < 0.0f)
                            cooldown = 0.0f;

                        repeat->SetCooldown(cooldown);
                    }

                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("Time in seconds to cooldown.\nHold button to increase speed.");

                    // CHARGES
                    if (ImGui::InputInt("Charges", &charges)) {

                        if (charges < 0)
                            charges = 0;

                        repeat->SetTriggerCharges(charges);
                    }
                    ImGui::SameLine();

                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("How many times a trigger can execute before automatically going inactive.\n0 = INFINITE.\nHold button to increase speed.");

                    // START ACTIVE
                    ImGui::Text("Start active? ");

                    ImGui::SameLine();

                    if (ImGui::RadioButton("Yes", &startActive, 1))
                        repeat->SetStartActive(true);

                    ImGui::SameLine();

                    if (ImGui::RadioButton("No", &startActive, 0))
                        repeat->SetStartActive(false);

                    break;
                }
                case SUBJECTS: {

                    // Hardcoded single event for demonstration purposes
                    if (ImGui::Button("New event", ImVec2(100, 25))) {
                        triggerEvent::EventStruct newStruct;
                        repeat->GetEventVector()->push_back(newStruct);
                    }

                    ImGui::NewLine();
                    ImGui::Columns(4);

                    ImGui::Text("Event");
                    ImGui::NextColumn();
                    ImGui::Text("Shape");
                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("When this shape collide with trigger volume the trigger will be executed.");

                    ImGui::NextColumn();
                    ImGui::Text("Target entity");
                    ImGui::SameLine();
                    ImGui::Text("[?]");
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("Entity to gather script from.");

                    ImGui::NextColumn();
                    ImGui::Text("Script method");
                    ImGui::Separator();

                    for (std::size_t i = 0; i < repeat->GetEventVector()->size(); ++i) {
                        ImGui::Columns(4);

                        std::array<const char*, 3> events = {
                            "OnEnter",
                            "OnRetain",
                            "OnLeave",
                        };

                        std::string labelEvent = "Type ";
                        labelEvent.append(std::to_string(i));
                        std::string labelShape = "Shape ";
                        labelShape.append(std::to_string(i));
                        std::string labelTarget = "Entity ";
                        labelTarget.append(std::to_string(i));
                        std::string labelScript = "Script ";
                        labelScript.append(std::to_string(i));

                        // Event type
                        int eventType = repeat->GetEventVector()->at(i).m_eventID;

                        if (ImGui::Combo(labelEvent.c_str(), &eventType, events.data(), events.size())) {
                            repeat->GetEventVector()->at(i).m_eventID = eventType;
                            repeat->GetEventVector()->at(i).check[0] = true;
                        }

                        // Subject
                        ImGui::NextColumn();
                        int shapeID = repeat->GetEventVector()->at(i).m_shapeID;
                        std::vector<std::string> entityWithShape;
                        for (std::size_t i = 0; i < Hymn().world.GetEntities().size(); ++i) {
                            if (Hymn().world.GetEntities().at(i)->GetComponent<Component::RigidBody>() != nullptr)
                                entityWithShape.push_back(Hymn().world.GetEntities().at(i)->name);
                        }

                        if (ImGui::Combo(labelShape.c_str(), &shapeID, entityWithShape)) {
                            repeat->GetEventVector()->at(i).m_shapeID = shapeID;

                            for (std::size_t j = 0; j < Hymn().world.GetEntities().size(); ++j) {
                                if (Hymn().world.GetEntities().at(j)->name == entityWithShape.at(shapeID)) {
                                    repeat->GetCollidedEntity()->push_back(Hymn().world.GetEntities().at(j));
                                    repeat->GetEventVector()->at(i).check[1] = true;
                                }
                            }
                        }

                        // Entity target
                        ImGui::NextColumn();
                        int targetID = repeat->GetEventVector()->at(i).m_targetID;
                        std::vector<std::string> entityName;

                        for (std::size_t i = 0; i < Hymn().world.GetEntities().size(); ++i) {
                            if (Hymn().world.GetEntities().at(i)->GetComponent<Component::Script>() != nullptr && Hymn().world.GetEntities().at(i)->name != comp.entity->name)
                                entityName.push_back(Hymn().world.GetEntities().at(i)->name);
                        }

                        if (ImGui::Combo(labelTarget.c_str(), &targetID, entityName)) {
                            repeat->GetEventVector()->at(i).m_targetID = targetID;

                            for (std::size_t j = 0; j < Hymn().world.GetEntities().size(); ++j) {

                                if (Hymn().world.GetEntities().at(j)->name == entityName.at(targetID)) {
                                    repeat->GetTargetEntity()->push_back(Hymn().world.GetEntities().at(j));
                                    repeat->GetEventVector()->at(i).check[2] = true;
                                }
                            }
                        }

                        // Script name
                        ImGui::NextColumn();
                        int scriptID = repeat->GetEventVector()->at(i).m_scriptID;

                        std::vector<std::string> scriptVector;

                        if (!repeat->GetTargetEntity()->empty()) {
                            for (std::size_t x = 0; x < repeat->GetTargetEntity()->size(); ++x) {

                                if (repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>() != nullptr && repeat->GetTargetEntity()->at(x)->name == entityName.at(targetID)) {

                                    for (std::size_t j = 0; j < repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>()->scriptFile->functionList.size(); ++j) {

                                        if (std::find(scriptVector.begin(), scriptVector.end(), repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>()->scriptFile->functionList.at(j)) == scriptVector.end())
                                            scriptVector.push_back(repeat->GetTargetEntity()->at(x)->GetComponent<Component::Script>()->scriptFile->functionList.at(j));
                                    }
                                }
                            }
                        }

                        if (!scriptVector.empty()) {
                            if (ImGui::Combo(labelScript.c_str(), &scriptID, scriptVector)) {
                                repeat->GetEventVector()->at(i).m_scriptID = scriptID;
                                repeat->GetTargetFunction()->push_back(scriptVector.at(scriptID));
                                repeat->GetEventVector()->at(i).check[3] = true;
                            }
                        }

                        ImGui::Separator();
                    }
                    break;
                }
            }

            ImGui::EndPopup();
        }
    }
}
<|endoftext|>


<commit_before>#include "hash_bytes.h"

// taken from:
// https://github.com/mirrors/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/hash_bytes.cc

namespace
{
  inline size_t
  unaligned_load(const char* p)
  {
    size_t result;
    __builtin_memcpy(&result, p, sizeof(result));
    return result;
  }

  // Loads n bytes, where 1 <= n < 8.
  inline size_t
  load_bytes(const char* p, int n)
  {
    size_t result = 0;
    --n;
    do
      result = (result << 8) + static_cast<unsigned char>(p[n]);
    while (--n >= 0);
    return result;
  }

  inline size_t
  shift_mix(size_t v)
  { return v ^ (v >> 47);}
}

namespace ndb {

// Implementation of Murmur hash for 64-bit size_t.
size_t
hash_bytes(const void *ptr, size_t len, size_t seed)
{
  static const size_t mul = (((size_t) 0xc6a4a793UL) << 32UL)
    + (size_t) 0x5bd1e995UL;
  const char* const buf = static_cast<const char*>(ptr);

  // Remove the bytes not divisible by the sizeof(size_t). This
  // allows the main loop to process the data as 64-bit integers.
  const int len_aligned = len & ~0x7;
  const char* const end = buf + len_aligned;
  size_t hash = seed ^ (len * mul);
  for (const char* p = buf; p != end; p += 8)
  {
    const size_t data = shift_mix(unaligned_load(p) * mul) * mul;
    hash ^= data;
    hash *= mul;
  }
  if ((len & 0x7) != 0)
  {
    const size_t data = load_bytes(end, len & 0x7);
    hash ^= data;
    hash *= mul;
  }
  hash = shift_mix(hash) * mul;
  hash = shift_mix(hash);
  return hash;
}

}
<commit_msg>remove unused file<commit_after><|endoftext|>


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

#include "PreCompiled.h"

#ifndef _PreComp_
# include <cfloat>
#endif

#include "PropertyModel.h"
#include "PropertyItem.h"

using namespace Gui::PropertyEditor;

/* TRANSLATOR Gui::PropertyEditor::PropertyModel */

PropertyModel::PropertyModel(QObject* parent)
    : QAbstractItemModel(parent)
{
    rootItem = static_cast<PropertyItem*>(PropertyItem::create());
}

PropertyModel::~PropertyModel()
{
    delete rootItem;
}

QModelIndex PropertyModel::buddy ( const QModelIndex & index ) const
{
    if (index.column() == 1)
        return index;
    return index.sibling(index.row(), 1);
}

int PropertyModel::columnCount ( const QModelIndex & parent ) const
{
    // <property, value>, hence always 2
    if (parent.isValid())
        return static_cast<PropertyItem*>(parent.internalPointer())->columnCount();
    else
        return rootItem->columnCount();
}

QVariant PropertyModel::data ( const QModelIndex & index, int role ) const
{
    if (!index.isValid())
        return QVariant();

    PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
    return item->data(index.column(), role);
}

bool PropertyModel::setData(const QModelIndex& index, const QVariant & value, int role)
{
    if (!index.isValid())
        return false;

    // we check whether the data has really changed, otherwise we ignore it
    if (role == Qt::EditRole) {
        PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
        QVariant data = item->data(index.column(), role);
        if (data.type() == QVariant::Double && value.type() == QVariant::Double) {
            // since we store some properties as floats we get some round-off
            // errors here. Thus, we use an epsilon here.
            // NOTE: Since 0.14 PropertyFloat uses double precision, so this is maybe unnecessary now?
            double d = data.toDouble();
            double v = value.toDouble();
            if (fabs(d-v) > FLT_EPSILON)
                return item->setData(value);
        }
        // Special case handling for quantities
        else if (data.canConvert<Base::Quantity>() && value.canConvert<Base::Quantity>()) {
            const Base::Quantity& val1 = data.value<Base::Quantity>();
            const Base::Quantity& val2 = value.value<Base::Quantity>();
            if (!(val1 == val2))
                return item->setData(value);
        }
        else if (data != value)
            return item->setData(value);
    }

    return true;
}

Qt::ItemFlags PropertyModel::flags(const QModelIndex &index) const
{
    PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
    return item->flags(index.column());
}

QModelIndex PropertyModel::index ( int row, int column, const QModelIndex & parent ) const
{
    PropertyItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<PropertyItem*>(parent.internalPointer());

    PropertyItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex PropertyModel::parent ( const QModelIndex & index ) const
{
    if (!index.isValid())
        return QModelIndex();

    PropertyItem *childItem = static_cast<PropertyItem*>(index.internalPointer());
    PropertyItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int PropertyModel::rowCount ( const QModelIndex & parent ) const
{
    PropertyItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<PropertyItem*>(parent.internalPointer());

    return parentItem->childCount();
}

QVariant PropertyModel::headerData (int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal) {
        if (role != Qt::DisplayRole)
            return QVariant();
        if (section == 0)
            return tr("Property");
        if (section == 1)
            return tr("Value");
    }

    return QVariant();
}

bool PropertyModel::setHeaderData (int, Qt::Orientation, const QVariant &, int)
{
    return false;
}

QStringList PropertyModel::propertyPathFromIndex(const QModelIndex& index) const
{
    QStringList path;
    if (index.isValid()) {
        PropertyItem* item = static_cast<PropertyItem*>(index.internalPointer());
        if (!item->isSeparator()) {
            do {
                path.push_front(item->propertyName());
                item = item->parent();
            }
            while (item != this->rootItem && item != 0);
        }
    }

    return path;
}

QModelIndex PropertyModel::propertyIndexFromPath(const QStringList& path) const
{
    QModelIndex parent;
    for (QStringList::const_iterator it = path.begin(); it != path.end(); ++it) {
        int rows = this->rowCount(parent);
        for (int i=0; i<rows; i++) {
            QModelIndex index = this->index(i, 0, parent);
            if (index.isValid()) {
                PropertyItem* item = static_cast<PropertyItem*>(index.internalPointer());
                if (item->propertyName() == *it) {
                    parent = index;
                    break;
                }
            }
        }
    }
    return parent;
}

void PropertyModel::buildUp(const PropertyModel::PropertyList& props)
{
    // fill up the listview with the properties
    rootItem->reset();

    // sort the properties into their groups
    std::map<std::string, std::vector<std::vector<App::Property*> > > propGroup;
    PropertyModel::PropertyList::const_iterator jt;
    for (jt = props.begin(); jt != props.end(); ++jt) {
        App::Property* prop = jt->second.front();
        const char* group = prop->getGroup();
        bool isEmpty = (group == 0 || group[0] == '\0');
        std::string grp = isEmpty ? "Base" : group;
        propGroup[grp].push_back(jt->second);
    }

    std::map<std::string, std::vector<std::vector<App::Property*> > >
        ::const_iterator kt;
    for (kt = propGroup.begin(); kt != propGroup.end(); ++kt) {
        // set group item
        PropertyItem* group = static_cast<PropertyItem*>(PropertySeparatorItem::create());
        group->setParent(rootItem);
        rootItem->appendChild(group);
        group->setPropertyName(QString::fromLatin1(kt->first.c_str()));

        // setup the items for the properties
        std::vector<std::vector<App::Property*> >::const_iterator it;
        for (it = kt->second.begin(); it != kt->second.end(); ++it) {
            App::Property* prop = it->front();
            QString editor = QString::fromLatin1(prop->getEditorName());
            if (!editor.isEmpty()) {
                Base::BaseClass* item = 0;
                try {
                    item = static_cast<Base::BaseClass*>(Base::Type::
                        createInstanceByName(prop->getEditorName(),true));
                }
                catch (...) {
                }
                if (!item) {
                    qWarning("No property item for type %s found\n", prop->getEditorName());
                    continue;
                }
                if (item->getTypeId().isDerivedFrom(PropertyItem::getClassTypeId())) {
                    PropertyItem* child = (PropertyItem*)item;
                    child->setParent(rootItem);
                    rootItem->appendChild(child);
                    child->setPropertyName(QString::fromLatin1(prop->getName()));
                    child->setPropertyData(*it);
                }
            }
        }
    }

    reset();
}

void PropertyModel::updateProperty(const App::Property& prop)
{
    int column = 1;
    int numChild = rootItem->childCount();
    for (int row=0; row<numChild; row++) {
        PropertyItem* child = rootItem->child(row);
        if (child->hasProperty(&prop)) {
            child->updateData();
            QModelIndex data = this->index(row, column, QModelIndex());
            if (data.isValid()) {
                dataChanged(data, data);
                updateChildren(child, column, data);
            }
            break;
        }
    }
}

void PropertyModel::appendProperty(const App::Property& prop)
{
    QString editor = QString::fromLatin1(prop.getEditorName());
    if (!editor.isEmpty()) {
        Base::BaseClass* item = 0;
        try {
            item = static_cast<Base::BaseClass*>(Base::Type::
                createInstanceByName(prop.getEditorName(),true));
        }
        catch (...) {
        }
        if (!item) {
            qWarning("No property item for type %s found\n", prop.getEditorName());
        }
        else if (item->getTypeId().isDerivedFrom(PropertyItem::getClassTypeId())) {
            // notify system to add new row
            int row = rootItem->childCount();
            beginInsertRows(QModelIndex(), row, row);

            PropertyItem* child = static_cast<PropertyItem*>(item);
            child->setParent(rootItem);
            rootItem->appendChild(child);
            child->setPropertyName(QString::fromLatin1(prop.getName()));
            std::vector<App::Property*> data;
            data.push_back(const_cast<App::Property*>(&prop));
            child->setPropertyData(data);

            endInsertRows();
        }
    }
}

void PropertyModel::removeProperty(const App::Property& prop)
{
    int numChild = rootItem->childCount();
    for (int row=0; row<numChild; row++) {
        PropertyItem* child = rootItem->child(row);
        if (child->hasProperty(&prop)) {
            if (child->removeProperty(&prop)) {
                removeRow(row, QModelIndex());
            }
            break;
        }
    }
}

void PropertyModel::updateChildren(PropertyItem* item, int column, const QModelIndex& parent)
{
    int numChild = item->childCount();
    if (numChild > 0) {
        QModelIndex topLeft = this->index(0, column, parent);
        QModelIndex bottomRight = this->index(numChild, column, parent);
        dataChanged(topLeft, bottomRight);
#if 0 // It seems we don't have to inform grand children
        for (int row=0; row<numChild; row++) {
            PropertyItem* child = item->child(row);
            QModelIndex data = this->index(row, column, parent);
            if (data.isValid()) {
                updateChildren(child, column, data);
            }
        }
#endif
    }
}

bool PropertyModel::removeRows(int row, int count, const QModelIndex& parent)
{
    PropertyItem* item;
    if (!parent.isValid())
        item = rootItem;
    else
        item = static_cast<PropertyItem*>(parent.internalPointer());

    int start = row;
    int end = row+count-1;
    beginRemoveRows(parent, start, end);
    item->removeChildren(start, end);
    endRemoveRows();
    return true;
}

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

#include "PreCompiled.h"

#ifndef _PreComp_
# include <cfloat>
#endif

#include "PropertyModel.h"
#include "PropertyItem.h"

using namespace Gui::PropertyEditor;

/* TRANSLATOR Gui::PropertyEditor::PropertyModel */

PropertyModel::PropertyModel(QObject* parent)
    : QAbstractItemModel(parent)
{
    rootItem = static_cast<PropertyItem*>(PropertyItem::create());
}

PropertyModel::~PropertyModel()
{
    delete rootItem;
}

QModelIndex PropertyModel::buddy ( const QModelIndex & index ) const
{
    if (index.column() == 1)
        return index;
    return index.sibling(index.row(), 1);
}

int PropertyModel::columnCount ( const QModelIndex & parent ) const
{
    // <property, value>, hence always 2
    if (parent.isValid())
        return static_cast<PropertyItem*>(parent.internalPointer())->columnCount();
    else
        return rootItem->columnCount();
}

QVariant PropertyModel::data ( const QModelIndex & index, int role ) const
{
    if (!index.isValid())
        return QVariant();

    PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
    return item->data(index.column(), role);
}

bool PropertyModel::setData(const QModelIndex& index, const QVariant & value, int role)
{
    if (!index.isValid())
        return false;

    // we check whether the data has really changed, otherwise we ignore it
    if (role == Qt::EditRole) {
        PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
        QVariant data = item->data(index.column(), role);
        if (data.type() == QVariant::Double && value.type() == QVariant::Double) {
            // since we store some properties as floats we get some round-off
            // errors here. Thus, we use an epsilon here.
            // NOTE: Since 0.14 PropertyFloat uses double precision, so this is maybe unnecessary now?
            double d = data.toDouble();
            double v = value.toDouble();
            if (fabs(d-v) > FLT_EPSILON)
                return item->setData(value);
        }
        // Special case handling for quantities
        else if (data.canConvert<Base::Quantity>() && value.canConvert<Base::Quantity>()) {
            const Base::Quantity& val1 = data.value<Base::Quantity>();
            const Base::Quantity& val2 = value.value<Base::Quantity>();
            if (!(val1 == val2))
                return item->setData(value);
        }
        else if (data != value)
            return item->setData(value);
    }

    return true;
}

Qt::ItemFlags PropertyModel::flags(const QModelIndex &index) const
{
    PropertyItem *item = static_cast<PropertyItem*>(index.internalPointer());
    return item->flags(index.column());
}

QModelIndex PropertyModel::index ( int row, int column, const QModelIndex & parent ) const
{
    PropertyItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<PropertyItem*>(parent.internalPointer());

    PropertyItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex PropertyModel::parent ( const QModelIndex & index ) const
{
    if (!index.isValid())
        return QModelIndex();

    PropertyItem *childItem = static_cast<PropertyItem*>(index.internalPointer());
    PropertyItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int PropertyModel::rowCount ( const QModelIndex & parent ) const
{
    PropertyItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<PropertyItem*>(parent.internalPointer());

    return parentItem->childCount();
}

QVariant PropertyModel::headerData (int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal) {
        if (role != Qt::DisplayRole)
            return QVariant();
        if (section == 0)
            return tr("Property");
        if (section == 1)
            return tr("Value");
    }

    return QVariant();
}

bool PropertyModel::setHeaderData (int, Qt::Orientation, const QVariant &, int)
{
    return false;
}

QStringList PropertyModel::propertyPathFromIndex(const QModelIndex& index) const
{
    QStringList path;
    if (index.isValid()) {
        PropertyItem* item = static_cast<PropertyItem*>(index.internalPointer());
        if (!item->isSeparator()) {
            do {
                path.push_front(item->propertyName());
                item = item->parent();
            }
            while (item != this->rootItem && item != 0);
        }
    }

    return path;
}

QModelIndex PropertyModel::propertyIndexFromPath(const QStringList& path) const
{
    QModelIndex parent;
    for (QStringList::const_iterator it = path.begin(); it != path.end(); ++it) {
        int rows = this->rowCount(parent);
        for (int i=0; i<rows; i++) {
            QModelIndex index = this->index(i, 0, parent);
            if (index.isValid()) {
                PropertyItem* item = static_cast<PropertyItem*>(index.internalPointer());
                if (item->propertyName() == *it) {
                    parent = index;
                    break;
                }
            }
        }
    }
    return parent;
}

void PropertyModel::buildUp(const PropertyModel::PropertyList& props)
{
    // fill up the listview with the properties
    rootItem->reset();

    beginResetModel();

    // sort the properties into their groups
    std::map<std::string, std::vector<std::vector<App::Property*> > > propGroup;
    PropertyModel::PropertyList::const_iterator jt;
    for (jt = props.begin(); jt != props.end(); ++jt) {
        App::Property* prop = jt->second.front();
        const char* group = prop->getGroup();
        bool isEmpty = (group == 0 || group[0] == '\0');
        std::string grp = isEmpty ? "Base" : group;
        propGroup[grp].push_back(jt->second);
    }

    std::map<std::string, std::vector<std::vector<App::Property*> > >
        ::const_iterator kt;
    for (kt = propGroup.begin(); kt != propGroup.end(); ++kt) {
        // set group item
        PropertyItem* group = static_cast<PropertyItem*>(PropertySeparatorItem::create());
        group->setParent(rootItem);
        rootItem->appendChild(group);
        group->setPropertyName(QString::fromLatin1(kt->first.c_str()));

        // setup the items for the properties
        std::vector<std::vector<App::Property*> >::const_iterator it;
        for (it = kt->second.begin(); it != kt->second.end(); ++it) {
            App::Property* prop = it->front();
            QString editor = QString::fromLatin1(prop->getEditorName());
            if (!editor.isEmpty()) {
                Base::BaseClass* item = 0;
                try {
                    item = static_cast<Base::BaseClass*>(Base::Type::
                        createInstanceByName(prop->getEditorName(),true));
                }
                catch (...) {
                }
                if (!item) {
                    qWarning("No property item for type %s found\n", prop->getEditorName());
                    continue;
                }
                if (item->getTypeId().isDerivedFrom(PropertyItem::getClassTypeId())) {
                    PropertyItem* child = (PropertyItem*)item;
                    child->setParent(rootItem);
                    rootItem->appendChild(child);
                    child->setPropertyName(QString::fromLatin1(prop->getName()));
                    child->setPropertyData(*it);
                }
            }
        }
    }

    endResetModel();
//    reset();
}

void PropertyModel::updateProperty(const App::Property& prop)
{
    int column = 1;
    int numChild = rootItem->childCount();
    for (int row=0; row<numChild; row++) {
        PropertyItem* child = rootItem->child(row);
        if (child->hasProperty(&prop)) {
            child->updateData();
            QModelIndex data = this->index(row, column, QModelIndex());
            if (data.isValid()) {
                dataChanged(data, data);
                updateChildren(child, column, data);
            }
            break;
        }
    }
}

void PropertyModel::appendProperty(const App::Property& prop)
{
    QString editor = QString::fromLatin1(prop.getEditorName());
    if (!editor.isEmpty()) {
        Base::BaseClass* item = 0;
        try {
            item = static_cast<Base::BaseClass*>(Base::Type::
                createInstanceByName(prop.getEditorName(),true));
        }
        catch (...) {
        }
        if (!item) {
            qWarning("No property item for type %s found\n", prop.getEditorName());
        }
        else if (item->getTypeId().isDerivedFrom(PropertyItem::getClassTypeId())) {
            // notify system to add new row
            int row = rootItem->childCount();
            beginInsertRows(QModelIndex(), row, row);

            PropertyItem* child = static_cast<PropertyItem*>(item);
            child->setParent(rootItem);
            rootItem->appendChild(child);
            child->setPropertyName(QString::fromLatin1(prop.getName()));
            std::vector<App::Property*> data;
            data.push_back(const_cast<App::Property*>(&prop));
            child->setPropertyData(data);

            endInsertRows();
        }
    }
}

void PropertyModel::removeProperty(const App::Property& prop)
{
    int numChild = rootItem->childCount();
    for (int row=0; row<numChild; row++) {
        PropertyItem* child = rootItem->child(row);
        if (child->hasProperty(&prop)) {
            if (child->removeProperty(&prop)) {
                removeRow(row, QModelIndex());
            }
            break;
        }
    }
}

void PropertyModel::updateChildren(PropertyItem* item, int column, const QModelIndex& parent)
{
    int numChild = item->childCount();
    if (numChild > 0) {
        QModelIndex topLeft = this->index(0, column, parent);
        QModelIndex bottomRight = this->index(numChild, column, parent);
        dataChanged(topLeft, bottomRight);
#if 0 // It seems we don't have to inform grand children
        for (int row=0; row<numChild; row++) {
            PropertyItem* child = item->child(row);
            QModelIndex data = this->index(row, column, parent);
            if (data.isValid()) {
                updateChildren(child, column, data);
            }
        }
#endif
    }
}

bool PropertyModel::removeRows(int row, int count, const QModelIndex& parent)
{
    PropertyItem* item;
    if (!parent.isValid())
        item = rootItem;
    else
        item = static_cast<PropertyItem*>(parent.internalPointer());

    int start = row;
    int end = row+count-1;
    beginRemoveRows(parent, start, end);
    item->removeChildren(start, end);
    endRemoveRows();
    return true;
}

#include "moc_PropertyModel.cpp"
<|endoftext|>


<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
                       Tobias Koenig <tokoe@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

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

#include <kabc/addressbook.h>
#include <kapplication.h>
#include <kcombobox.h>
#include <klocale.h>

#include <QComboBox>
#include <QGroupBox>
#include <QLabel>
#include <QLayout>
#include <Q3ListView>
#include <QPushButton>
#include <QRadioButton>
#include <QStringList>

//Added by qt3to4:
#include <QVBoxLayout>
#include <QFrame>
#include <QGridLayout>
#include <ktoolinvocation.h>
#include <kglobal.h>

#include <libkdepim/categoryselectdialog.h>

#include "core.h"
#include "kabprefs.h"

#include "xxportselectdialog.h"

XXPortSelectDialog::XXPortSelectDialog( KAB::Core *core, bool sort,
                                        QWidget* parent )
    : KDialog( parent ), mCore( core ),
      mUseSorting( sort )
{
  setCaption( i18n( "Choose Which Contacts to Export" ) );
  setButtons( Help | Ok | Cancel );
  setDefaultButton( Ok );
  setModal( true );
  showButtonSeparator( true );

  initGUI();

  connect( mFiltersCombo, SIGNAL( activated( int ) ),
           SLOT( filterChanged( int ) ) );

  // setup filters
  mFilters = Filter::restore( KGlobal::config().data(), "Filter" );
  Filter::List::ConstIterator filterIt;
  QStringList filters;
  for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt )
    filters.append( (*filterIt).name() );

  mFiltersCombo->addItems( filters );
  mUseFilters->setEnabled( filters.count() > 0 );

  // setup categories
  const QStringList categories = KABPrefs::instance()->customCategories();
  mCategoriesView->setCategories( categories );
  mUseCategories->setEnabled( categories.count() > 0 );

  int count = mCore->selectedUIDs().count();
  mUseSelection->setEnabled( count != 0 );
  mUseSelection->setChecked( count  > 0 );

  mSortTypeCombo->addItem( i18n( "Ascending" ) );
  mSortTypeCombo->addItem( i18n( "Descending" ) );

  mFields = mCore->addressBook()->fields( KABC::Field::All );
  KABC::Field::List::ConstIterator fieldIt;
  for ( fieldIt = mFields.begin(); fieldIt != mFields.end(); ++fieldIt )
    mFieldCombo->addItem( (*fieldIt)->label() );
  connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
}

KABC::AddresseeList XXPortSelectDialog::contacts()
{
  const QStringList selection = mCore->selectedUIDs();

  KABC::AddresseeList list;
  if ( mUseSelection->isChecked() ) {
    QStringList::ConstIterator it;
    for ( it = selection.begin(); it != selection.end(); ++it ) {
      KABC::Addressee addr = mCore->addressBook()->findByUid( *it );
      if ( !addr.isEmpty() )
        list.append( addr );
    }
  } else if ( mUseFilters->isChecked() ) {
    // find contacts that can pass selected filter
    Filter::List::ConstIterator filterIt;
    for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt )
      if ( (*filterIt).name() == mFiltersCombo->currentText() )
        break;

    KABC::AddressBook::Iterator it;
    for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) {
      if ( (*filterIt).filterAddressee( *it ) )
        list.append( *it );
    }
  } else if ( mUseCategories->isChecked() ) {
    const QStringList categorieList = categories();

    KABC::AddressBook::ConstIterator it;
    KABC::AddressBook::ConstIterator addressBookEnd( mCore->addressBook()->end() );
    for ( it = mCore->addressBook()->begin(); it != addressBookEnd; ++it ) {
      const QStringList tmp( (*it).categories() );
      QStringList::ConstIterator tmpIt;
      for ( tmpIt = tmp.begin(); tmpIt != tmp.end(); ++tmpIt )
        if ( categorieList.contains( *tmpIt ) ) {
          list.append( *it );
          break;
        }
    }
  } else {
    // create a string list of all entries:
    KABC::AddressBook::ConstIterator it;
    for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it )
      list.append( *it );
  }

  if ( mUseSorting ) {
    list.setReverseSorting( mSortTypeCombo->currentIndex() == 1 );
    int pos = mFieldCombo->currentIndex();
    if ( pos < mFields.count() )
      list.sortByField( mFields[ pos ] );
  }

  return list;
}

QStringList XXPortSelectDialog::categories() const
{
  QString lst;
  return mCategoriesView->selectedCategories( lst );
}

void XXPortSelectDialog::filterChanged( int )
{
  mUseFilters->setChecked( true );
}

void XXPortSelectDialog::categoryClicked()
{
  mUseCategories->setChecked( true );
}

void XXPortSelectDialog::slotHelp()
{
  KToolInvocation::invokeHelp( "import-and-export" );
}

void XXPortSelectDialog::initGUI()
{
  QWidget *page = new QWidget( this );
  setMainWidget( page );

  QVBoxLayout *topLayout = new QVBoxLayout( page );
  topLayout->setSpacing( KDialog::spacingHint() );
  topLayout->setMargin( 0 );

  QLabel *label = new QLabel( i18n( "Which contacts do you want to export?" ), page );
  topLayout->addWidget( label );

  mButtonGroup = new QGroupBox( i18n( "Selection" ), page );
  QGridLayout *groupLayout = new QGridLayout();
  groupLayout->setSpacing( KDialog::spacingHint() );
  groupLayout->setMargin( KDialog::marginHint() );
  groupLayout->setAlignment( Qt::AlignTop );
  mButtonGroup->setLayout( groupLayout );

  mUseWholeBook = new QRadioButton( i18n( "&All contacts" ), mButtonGroup );
  mUseWholeBook->setChecked( true );
  mUseWholeBook->setWhatsThis( i18n( "Export the entire address book" ) );
  groupLayout->addWidget( mUseWholeBook, 0, 0 );
  mUseSelection = new QRadioButton( i18np( "&Selected contact", "&Selected contacts (%1 selected)", mCore->selectedUIDs().count() ), mButtonGroup );
  mUseSelection->setWhatsThis( i18n( "Only export contacts selected in KAddressBook.\n"
                                        "This option is disabled if no contacts are selected." ) );
  groupLayout->addWidget( mUseSelection, 1, 0 );

  mUseFilters = new QRadioButton( i18n( "Contacts matching &filter" ), mButtonGroup );
  mUseFilters->setWhatsThis( i18n( "Only export contacts matching the selected filter.\n"
                                     "This option is disabled if you have not defined any filters" ) );
  groupLayout->addWidget( mUseFilters, 2, 0 );

  mUseCategories = new QRadioButton( i18n( "Category &members" ), mButtonGroup );
  mUseCategories->setWhatsThis( i18n( "Only export contacts who are members of a category that is checked on the list to the left.\n"
                                       "This option is disabled if you have no categories." ) );
  groupLayout->addWidget( mUseCategories, 3, 0, Qt::AlignTop );

  mFiltersCombo = new QComboBox( mButtonGroup );
  mFiltersCombo->setEditable( false );
  mFiltersCombo->setWhatsThis( i18n( "Select a filter to decide which contacts to export." ) );
  groupLayout->addWidget( mFiltersCombo, 2, 1 );

  mCategoriesView = new KPIM::CategorySelectWidget( mButtonGroup, KABPrefs::instance() );
  mCategoriesView->hideButton();
  mCategoriesView->layout()->setMargin( 0 );
  mCategoriesView->setWhatsThis( i18n( "Check the categories whose members you want to print." ) );
  groupLayout->addWidget( mCategoriesView, 3, 1 );
  connect( mCategoriesView->listView(), SIGNAL( clicked( Q3ListView* ) ),
           this, SLOT( categoryClicked() ) );

  topLayout->addWidget( mButtonGroup );

  QGroupBox *sortingGroup = new QGroupBox( i18n( "Sorting" ), page );
  QGridLayout *sortLayout = new QGridLayout();
  sortLayout->setSpacing( KDialog::spacingHint() );
  sortLayout->setAlignment( Qt::AlignTop );
  sortingGroup->setLayout( sortLayout );

  label = new QLabel( i18n( "Criterion:" ), sortingGroup );
  sortLayout->addWidget( label, 0, 0 );

  mFieldCombo = new KComboBox( false, sortingGroup );
  sortLayout->addWidget( mFieldCombo, 0, 1 );

  label = new QLabel( i18n( "Order:" ), sortingGroup );
  sortLayout->addWidget( label, 1, 0 );

  mSortTypeCombo = new KComboBox( false, sortingGroup );
  sortLayout->addWidget( mSortTypeCombo, 1, 1 );

  topLayout->addWidget( sortingGroup );

  if ( !mUseSorting )
    sortingGroup->hide();
}

#include "xxportselectdialog.moc"
<commit_msg>* fixed signal/slot connection<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
                       Tobias Koenig <tokoe@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

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

#include <kabc/addressbook.h>
#include <kapplication.h>
#include <kcombobox.h>
#include <klocale.h>

#include <QComboBox>
#include <QGroupBox>
#include <QLabel>
#include <QLayout>
#include <Q3ListView>
#include <QPushButton>
#include <QRadioButton>
#include <QStringList>

//Added by qt3to4:
#include <QVBoxLayout>
#include <QFrame>
#include <QGridLayout>
#include <ktoolinvocation.h>
#include <kglobal.h>

#include <libkdepim/categoryselectdialog.h>

#include "core.h"
#include "kabprefs.h"

#include "xxportselectdialog.h"

XXPortSelectDialog::XXPortSelectDialog( KAB::Core *core, bool sort,
                                        QWidget* parent )
    : KDialog( parent ), mCore( core ),
      mUseSorting( sort )
{
  setCaption( i18n( "Choose Which Contacts to Export" ) );
  setButtons( Help | Ok | Cancel );
  setDefaultButton( Ok );
  setModal( true );
  showButtonSeparator( true );

  initGUI();

  connect( mFiltersCombo, SIGNAL( activated( int ) ),
           SLOT( filterChanged( int ) ) );

  // setup filters
  mFilters = Filter::restore( KGlobal::config().data(), "Filter" );
  Filter::List::ConstIterator filterIt;
  QStringList filters;
  for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt )
    filters.append( (*filterIt).name() );

  mFiltersCombo->addItems( filters );
  mUseFilters->setEnabled( filters.count() > 0 );

  // setup categories
  const QStringList categories = KABPrefs::instance()->customCategories();
  mCategoriesView->setCategories( categories );
  mUseCategories->setEnabled( categories.count() > 0 );

  int count = mCore->selectedUIDs().count();
  mUseSelection->setEnabled( count != 0 );
  mUseSelection->setChecked( count  > 0 );

  mSortTypeCombo->addItem( i18n( "Ascending" ) );
  mSortTypeCombo->addItem( i18n( "Descending" ) );

  mFields = mCore->addressBook()->fields( KABC::Field::All );
  KABC::Field::List::ConstIterator fieldIt;
  for ( fieldIt = mFields.begin(); fieldIt != mFields.end(); ++fieldIt )
    mFieldCombo->addItem( (*fieldIt)->label() );
  connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
}

KABC::AddresseeList XXPortSelectDialog::contacts()
{
  const QStringList selection = mCore->selectedUIDs();

  KABC::AddresseeList list;
  if ( mUseSelection->isChecked() ) {
    QStringList::ConstIterator it;
    for ( it = selection.begin(); it != selection.end(); ++it ) {
      KABC::Addressee addr = mCore->addressBook()->findByUid( *it );
      if ( !addr.isEmpty() )
        list.append( addr );
    }
  } else if ( mUseFilters->isChecked() ) {
    // find contacts that can pass selected filter
    Filter::List::ConstIterator filterIt;
    for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt )
      if ( (*filterIt).name() == mFiltersCombo->currentText() )
        break;

    KABC::AddressBook::Iterator it;
    for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) {
      if ( (*filterIt).filterAddressee( *it ) )
        list.append( *it );
    }
  } else if ( mUseCategories->isChecked() ) {
    const QStringList categorieList = categories();

    KABC::AddressBook::ConstIterator it;
    KABC::AddressBook::ConstIterator addressBookEnd( mCore->addressBook()->end() );
    for ( it = mCore->addressBook()->begin(); it != addressBookEnd; ++it ) {
      const QStringList tmp( (*it).categories() );
      QStringList::ConstIterator tmpIt;
      for ( tmpIt = tmp.begin(); tmpIt != tmp.end(); ++tmpIt )
        if ( categorieList.contains( *tmpIt ) ) {
          list.append( *it );
          break;
        }
    }
  } else {
    // create a string list of all entries:
    KABC::AddressBook::ConstIterator it;
    for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it )
      list.append( *it );
  }

  if ( mUseSorting ) {
    list.setReverseSorting( mSortTypeCombo->currentIndex() == 1 );
    int pos = mFieldCombo->currentIndex();
    if ( pos < mFields.count() )
      list.sortByField( mFields[ pos ] );
  }

  return list;
}

QStringList XXPortSelectDialog::categories() const
{
  QString lst;
  return mCategoriesView->selectedCategories( lst );
}

void XXPortSelectDialog::filterChanged( int )
{
  mUseFilters->setChecked( true );
}

void XXPortSelectDialog::categoryClicked()
{
  mUseCategories->setChecked( true );
}

void XXPortSelectDialog::slotHelp()
{
  KToolInvocation::invokeHelp( "import-and-export" );
}

void XXPortSelectDialog::initGUI()
{
  QWidget *page = new QWidget( this );
  setMainWidget( page );

  QVBoxLayout *topLayout = new QVBoxLayout( page );
  topLayout->setSpacing( KDialog::spacingHint() );
  topLayout->setMargin( 0 );

  QLabel *label = new QLabel( i18n( "Which contacts do you want to export?" ), page );
  topLayout->addWidget( label );

  mButtonGroup = new QGroupBox( i18n( "Selection" ), page );
  QGridLayout *groupLayout = new QGridLayout();
  groupLayout->setSpacing( KDialog::spacingHint() );
  groupLayout->setMargin( KDialog::marginHint() );
  groupLayout->setAlignment( Qt::AlignTop );
  mButtonGroup->setLayout( groupLayout );

  mUseWholeBook = new QRadioButton( i18n( "&All contacts" ), mButtonGroup );
  mUseWholeBook->setChecked( true );
  mUseWholeBook->setWhatsThis( i18n( "Export the entire address book" ) );
  groupLayout->addWidget( mUseWholeBook, 0, 0 );
  mUseSelection = new QRadioButton( i18np( "&Selected contact", "&Selected contacts (%1 selected)", mCore->selectedUIDs().count() ), mButtonGroup );
  mUseSelection->setWhatsThis( i18n( "Only export contacts selected in KAddressBook.\n"
                                        "This option is disabled if no contacts are selected." ) );
  groupLayout->addWidget( mUseSelection, 1, 0 );

  mUseFilters = new QRadioButton( i18n( "Contacts matching &filter" ), mButtonGroup );
  mUseFilters->setWhatsThis( i18n( "Only export contacts matching the selected filter.\n"
                                     "This option is disabled if you have not defined any filters" ) );
  groupLayout->addWidget( mUseFilters, 2, 0 );

  mUseCategories = new QRadioButton( i18n( "Category &members" ), mButtonGroup );
  mUseCategories->setWhatsThis( i18n( "Only export contacts who are members of a category that is checked on the list to the left.\n"
                                       "This option is disabled if you have no categories." ) );
  groupLayout->addWidget( mUseCategories, 3, 0, Qt::AlignTop );

  mFiltersCombo = new QComboBox( mButtonGroup );
  mFiltersCombo->setEditable( false );
  mFiltersCombo->setWhatsThis( i18n( "Select a filter to decide which contacts to export." ) );
  groupLayout->addWidget( mFiltersCombo, 2, 1 );

  mCategoriesView = new KPIM::CategorySelectWidget( mButtonGroup, KABPrefs::instance() );
  mCategoriesView->hideButton();
  mCategoriesView->layout()->setMargin( 0 );
  mCategoriesView->setWhatsThis( i18n( "Check the categories whose members you want to print." ) );
  groupLayout->addWidget( mCategoriesView, 3, 1 );
  connect( mCategoriesView->listView(),
           SIGNAL( itemClicked( QTreeWidgetItem *, int ) ),
           this, SLOT( categoryClicked() ) );

  topLayout->addWidget( mButtonGroup );

  QGroupBox *sortingGroup = new QGroupBox( i18n( "Sorting" ), page );
  QGridLayout *sortLayout = new QGridLayout();
  sortLayout->setSpacing( KDialog::spacingHint() );
  sortLayout->setAlignment( Qt::AlignTop );
  sortingGroup->setLayout( sortLayout );

  label = new QLabel( i18n( "Criterion:" ), sortingGroup );
  sortLayout->addWidget( label, 0, 0 );

  mFieldCombo = new KComboBox( false, sortingGroup );
  sortLayout->addWidget( mFieldCombo, 0, 1 );

  label = new QLabel( i18n( "Order:" ), sortingGroup );
  sortLayout->addWidget( label, 1, 0 );

  mSortTypeCombo = new KComboBox( false, sortingGroup );
  sortLayout->addWidget( mSortTypeCombo, 1, 1 );

  topLayout->addWidget( sortingGroup );

  if ( !mUseSorting )
    sortingGroup->hide();
}

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