<commit_before>#include <kglt/kglt.h>

#include "spindash/spindash.h"
#include "spindash/character.h"

class KGLTGeometryRenderer {
public:
    KGLTGeometryRenderer(kglt::Scene& scene, kglt::StageID stage_id=kglt::StageID()):
        scene_(scene),
        stage_id_(stage_id) {

        stage().new_material_with_name_from_file("diffuse_render", "kglt/materials/diffuse_render.kglm", false);

        auto mat = stage().material(stage().get_material_with_name("diffuse_render"));
        mat->technique().pass(0).set_polygon_mode(kglt::POLYGON_MODE_LINE);
    }

    SDGeometryHandle compile_geometry(SDRenderMode mode, SDVec2* vertices, SDuint numVertices, SDuint* indices, SDuint numIndices) {
        kglt::MeshID new_mesh = stage().new_mesh();

        {
            auto mesh = stage().mesh(new_mesh);
            auto submesh = mesh->new_submesh(
                stage().get_material_with_name("diffuse_render"),
                (mode == SD_RENDER_MODE_TRIANGLES) ? kglt::MESH_ARRANGEMENT_TRIANGLES : kglt::MESH_ARRANGEMENT_LINES, true
            );

            for(SDuint i = 0; i < numVertices; ++i) {
                mesh->shared_data().position(vertices[i]);
                mesh->shared_data().diffuse(kglt::Colour::WHITE);
                mesh->shared_data().move_next();
            }

            for(SDuint i = 0; i < numIndices; ++i) {
                mesh->submesh(submesh).index_data().index(indices[i]);
            }

            mesh->submesh(submesh).index_data().done();
            mesh->shared_data().done();

        }

        kglt::ActorID new_actor = stage().new_actor(new_mesh);
        return new_actor.value();
    }

    void render_geometry(SDGeometryHandle handle, const SDVec2* translation, const SDfloat angle) {
        auto actor = stage().actor(kglt::ActorID(handle));
        actor->move_to(translation->x, translation->y);
        actor->rotate_to(kglt::Degrees(angle));
    }

    static SDGeometryHandle compile_geometry_callback(SDRenderMode mode, SDVec2* vertices, SDuint numVertices, SDuint* indices, SDuint numIndexes, void* userData) {
        auto bound_func = std::bind(&KGLTGeometryRenderer::compile_geometry,
            (KGLTGeometryRenderer*) userData,
            std::placeholders::_1,
            std::placeholders::_2,
            std::placeholders::_3,
            std::placeholders::_4,
            std::placeholders::_5
        );

        return bound_func(mode, vertices, numVertices, indices, numIndexes);
    }

    static void render_geometry_callback(SDGeometryHandle handle, const SDVec2* translation, const SDfloat angle, void* userData) {
        auto bound_func = std::bind(&KGLTGeometryRenderer::render_geometry,
            (KGLTGeometryRenderer*) userData,
            std::placeholders::_1,
            std::placeholders::_2,
            std::placeholders::_3
        );

        bound_func(handle, translation, angle);
    }

private:
    kglt::Stage& stage() {
        return scene_.stage(stage_id_);
    }

    kglt::Scene& scene_;
    kglt::StageID stage_id_;

    std::map<SDGeometryHandle, kglt::MeshID> dynamic_meshes_;
    std::map<SDGeometryHandle, kglt::ActorID> dynamic_actors_;
};

class Playground : public kglt::App {
public:
    Playground() {
        renderer_.reset(new KGLTGeometryRenderer(scene()));
    }

    bool do_init() {
        sdCharacterOverrideSetting("VERTICAL_SENSOR_EXTENSION_LENGTH", 16.0 / 40.0);

        world = sdWorldCreate();

        sdWorldSetCompileGeometryCallback(world, &KGLTGeometryRenderer::compile_geometry_callback, renderer_.get());
        sdWorldSetRenderGeometryCallback(world, &KGLTGeometryRenderer::render_geometry_callback, renderer_.get());

        build_world();

        scene().camera().set_orthographic_projection(-10, 10, -10, 10);

        return true;
    }

    void do_step(double dt) {
        if(initialized()) {
            sdWorldStep(world, dt);
            sdWorldRender(world);
        }
    }

    void do_cleanup() {
        sdWorldDestroy(world);
    }

private:
    SDuint world = 0;
    SDuint sonic = 0;
    SDuint spring = 0;
    SDuint spring2 = 0;

    std::shared_ptr<KGLTGeometryRenderer> renderer_;

    bool on_key_press(SDL_Keysym key) {
        if(key.scancode == SDL_SCANCODE_SPACE) {
            debug_break = true;
        }
        return false;
    }

    bool while_key_pressed(SDL_Keysym key, double) {
        switch(key.scancode) {
            case SDL_SCANCODE_RIGHT:
                sdCharacterRightPressed(sonic);
            break;
            case SDL_SCANCODE_LEFT:
                sdCharacterLeftPressed(sonic);
            break;
            case SDL_SCANCODE_DOWN:
                sdCharacterDownPressed(sonic);
            break;
            case SDL_SCANCODE_D:
                sdCharacterJumpPressed(sonic);
            break;
            default:break;
        }

        return false;
    }

    void create_floor_plane(SDuint world) {
        kmVec2 points[6];

        kmVec2Fill(&points[0], -10.0f, 0.0f);
        kmVec2Fill(&points[1], -10.0f, -1.0f);
        kmVec2Fill(&points[2], 10.0f, 0.0f);

        kmVec2Fill(&points[3], 10.0f, 0.0f);
        kmVec2Fill(&points[4], -10.0f, -1.0f);
        kmVec2Fill(&points[5], 10.0f, -1.0f);

        sdWorldAddMesh(world, 2, points);
    }

    void build_world() {
        sonic = sdCharacterCreate(world);

        sdObjectSetPosition(sonic, 3.0f, 3.0f);
        create_floor_plane(world);

        /*kmVec2 slope[3];
        kmVec2Fill(&slope[0], 3.0f, 0.0f);
        kmVec2Fill(&slope[1], 10.0f, 0.0f);
        kmVec2Fill(&slope[2], 10.0f, 3.0f);
        sdWorldAddTriangle(world, slope);*/

        kmVec2 wall[4];

        kmVec2Fill(&wall[0], -10.0f, 0.0f);
        kmVec2Fill(&wall[1], -5.0f, 0.0f);
        kmVec2Fill(&wall[2], -5.0f, 5.0f);
        kmVec2Fill(&wall[3], -10.0f, 5.0f);
        sdWorldAddBox(world, wall);

        /*kmVec2 platform[4];
        kmVec2Fill(&platform[0], 1.0f, 1.5f);
        kmVec2Fill(&platform[1], 3.0f, 1.5f);
        kmVec2Fill(&platform[2], 3.0f, 2.0f);
        kmVec2Fill(&platform[3], 1.0f, 2.0f);
        sdWorldAddBox(world, platform);*/

        spring = sdSpringCreate(world, 0, 10.0f / 40.0f);
        sdObjectSetPosition(spring, -4.75f, 0.125f);

     /*   spring2 = sdSpringCreate(world, -45.0f, 10.0f/40.0f);
        sdObjectSetPosition(spring2, 2.0f, 2.25f);*/

        kmVec2 triangle[3];
        kmVec2Fill(&triangle[0], 5, 0);
        kmVec2Fill(&triangle[1], 10, 0);
        kmVec2Fill(&triangle[2], 10, 2);
        sdWorldAddTriangle(world, triangle);

        //sdWorldConstructLoop(world, 4.0f, 8.0f, 8.0f);
    }
};

int main(int argc, char* argv[]) {
    Playground app;
    return app.run();
}

<commit_msg>Update for latest KGLT<commit_after>#include <kglt/kglt.h>

#include "spindash/spindash.h"
#include "spindash/character.h"

class KGLTGeometryRenderer {
public:
    KGLTGeometryRenderer(kglt::WindowBase& window, kglt::StageID stage_id=kglt::StageID()):
        window_(window),
        stage_id_(stage_id) {

        stage()->new_material_with_alias_from_file("diffuse_render", "kglt/materials/diffuse_render.kglm", false);

        auto mat = stage()->material(stage()->get_material_with_alias("diffuse_render"));
        mat->pass(0).set_polygon_mode(kglt::POLYGON_MODE_LINE);
    }

    SDGeometryHandle compile_geometry(SDRenderMode mode, SDVec2* vertices, SDuint numVertices, SDuint* indices, SDuint numIndices) {
        kglt::MeshID new_mesh = stage()->new_mesh();

        {
            auto mesh = stage()->mesh(new_mesh);
            auto submesh = mesh->new_submesh(
                stage()->get_material_with_alias("diffuse_render"),
                (mode == SD_RENDER_MODE_TRIANGLES) ? kglt::MESH_ARRANGEMENT_TRIANGLES : kglt::MESH_ARRANGEMENT_LINES, true
            );

            for(SDuint i = 0; i < numVertices; ++i) {
                mesh->shared_data().position(vertices[i]);
                mesh->shared_data().diffuse(kglt::Colour::WHITE);
                mesh->shared_data().move_next();
            }

            for(SDuint i = 0; i < numIndices; ++i) {
                mesh->submesh(submesh).index_data().index(indices[i]);
            }

            mesh->submesh(submesh).index_data().done();
            mesh->shared_data().done();

        }

        kglt::ActorID new_actor = stage()->new_actor(new_mesh);
        return new_actor.value();
    }

    void render_geometry(SDGeometryHandle handle, const SDVec2* translation, const SDfloat angle) {
        auto actor = stage()->actor(kglt::ActorID(handle));
        actor->move_to(translation->x, translation->y);
        actor->rotate_to(kglt::Degrees(angle));
    }

    static SDGeometryHandle compile_geometry_callback(SDRenderMode mode, SDVec2* vertices, SDuint numVertices, SDuint* indices, SDuint numIndexes, void* userData) {
        auto bound_func = std::bind(&KGLTGeometryRenderer::compile_geometry,
            (KGLTGeometryRenderer*) userData,
            std::placeholders::_1,
            std::placeholders::_2,
            std::placeholders::_3,
            std::placeholders::_4,
            std::placeholders::_5
        );

        return bound_func(mode, vertices, numVertices, indices, numIndexes);
    }

    static void render_geometry_callback(SDGeometryHandle handle, const SDVec2* translation, const SDfloat angle, void* userData) {
        auto bound_func = std::bind(&KGLTGeometryRenderer::render_geometry,
            (KGLTGeometryRenderer*) userData,
            std::placeholders::_1,
            std::placeholders::_2,
            std::placeholders::_3
        );

        bound_func(handle, translation, angle);
    }

private:
    kglt::StagePtr stage() {
        return window_.stage(stage_id_);
    }

    kglt::WindowBase& window_;
    kglt::StageID stage_id_;

    std::map<SDGeometryHandle, kglt::MeshID> dynamic_meshes_;
    std::map<SDGeometryHandle, kglt::ActorID> dynamic_actors_;
};

class Playground : public kglt::Application {
public:
    Playground() {
        renderer_.reset(new KGLTGeometryRenderer(window()));
    }

    bool do_init() {
        sdCharacterOverrideSetting("VERTICAL_SENSOR_EXTENSION_LENGTH", 16.0 / 40.0);

        world = sdWorldCreate();

        sdWorldSetCompileGeometryCallback(world, &KGLTGeometryRenderer::compile_geometry_callback, renderer_.get());
        sdWorldSetRenderGeometryCallback(world, &KGLTGeometryRenderer::render_geometry_callback, renderer_.get());

        build_world();

        window().camera()->set_orthographic_projection(-10, 10, -10, 10);

        return true;
    }

    void do_step(double dt) {
        if(initialized()) {
            sdWorldStep(world, dt);
            sdWorldRender(world);
        }
    }

    void do_cleanup() {
        sdWorldDestroy(world);
    }

private:
    SDuint world = 0;
    SDuint sonic = 0;
    SDuint spring = 0;
    SDuint spring2 = 0;

    std::shared_ptr<KGLTGeometryRenderer> renderer_;

    bool on_key_press(SDL_Keysym key) {
        if(key.scancode == SDL_SCANCODE_SPACE) {
            debug_break = true;
        }
        return false;
    }

    bool while_key_pressed(SDL_Keysym key, double) {
        switch(key.scancode) {
            case SDL_SCANCODE_RIGHT:
                sdCharacterRightPressed(sonic);
            break;
            case SDL_SCANCODE_LEFT:
                sdCharacterLeftPressed(sonic);
            break;
            case SDL_SCANCODE_DOWN:
                sdCharacterDownPressed(sonic);
            break;
            case SDL_SCANCODE_D:
                sdCharacterJumpPressed(sonic);
            break;
            default:break;
        }

        return false;
    }

    void create_floor_plane(SDuint world) {
        kmVec2 points[6];

        kmVec2Fill(&points[0], -10.0f, 0.0f);
        kmVec2Fill(&points[1], -10.0f, -1.0f);
        kmVec2Fill(&points[2], 10.0f, 0.0f);

        kmVec2Fill(&points[3], 10.0f, 0.0f);
        kmVec2Fill(&points[4], -10.0f, -1.0f);
        kmVec2Fill(&points[5], 10.0f, -1.0f);

        sdWorldAddMesh(world, 2, points);
    }

    void build_world() {
        sonic = sdCharacterCreate(world);

        sdObjectSetPosition(sonic, 3.0f, 3.0f);
        create_floor_plane(world);

        /*kmVec2 slope[3];
        kmVec2Fill(&slope[0], 3.0f, 0.0f);
        kmVec2Fill(&slope[1], 10.0f, 0.0f);
        kmVec2Fill(&slope[2], 10.0f, 3.0f);
        sdWorldAddTriangle(world, slope);*/

        kmVec2 wall[4];

        kmVec2Fill(&wall[0], -10.0f, 0.0f);
        kmVec2Fill(&wall[1], -5.0f, 0.0f);
        kmVec2Fill(&wall[2], -5.0f, 5.0f);
        kmVec2Fill(&wall[3], -10.0f, 5.0f);
        sdWorldAddBox(world, wall);

        /*kmVec2 platform[4];
        kmVec2Fill(&platform[0], 1.0f, 1.5f);
        kmVec2Fill(&platform[1], 3.0f, 1.5f);
        kmVec2Fill(&platform[2], 3.0f, 2.0f);
        kmVec2Fill(&platform[3], 1.0f, 2.0f);
        sdWorldAddBox(world, platform);*/

        spring = sdSpringCreate(world, 0, 10.0f / 40.0f);
        sdObjectSetPosition(spring, -4.75f, 0.125f);

     /*   spring2 = sdSpringCreate(world, -45.0f, 10.0f/40.0f);
        sdObjectSetPosition(spring2, 2.0f, 2.25f);*/

        kmVec2 triangle[3];
        kmVec2Fill(&triangle[0], 5, 0);
        kmVec2Fill(&triangle[1], 10, 0);
        kmVec2Fill(&triangle[2], 10, 2);
        sdWorldAddTriangle(world, triangle);

        //sdWorldConstructLoop(world, 4.0f, 8.0f, 8.0f);
    }
};

int main(int argc, char* argv[]) {
    Playground app;
    return app.run();
}

<|endoftext|>


<commit_before>#include "card_selector.h"
#include <QLayout>
#include <QVBoxLayout>
#include <cards/standard-36-deck.h>
#include <QPushButton>
#include <type_traits>
#include <exception>

#include <QFrame>

template<class T>
typename std::enable_if<std::is_same<T, QComboBox>::value>::type SelectData(T* comboBox, int data) {
	int index = comboBox->findData(data);
	if (index == -1)
		throw std::runtime_error("Unknown data");
	comboBox->setCurrentIndex(index);
}

GuiCardSelector::GuiCardSelector(int suit, int rank, bool inversed, QWidget* parent) : QWidget(parent) {
	CreateElements();
	PopulateSuits();
	PopulateRanks();
	CreateLayout();

	SelectData(this->suit, suit);
	SelectData(this->rank, rank);
	inverse->setChecked(inversed);
}

void GuiCardSelector::CreateElements() {
	suit = new QComboBox();
	rank = new QComboBox();
	inverse = new QCheckBox(tr("Inverse"));
}

void GuiCardSelector::PopulateSuits() {
	suit->addItem(tr("Any suit"), (int)-1);
	suit->addItem(tr("Diamond"), (int)standard_36_deck::Suits::Diamonds);
	suit->addItem(tr("Spade"), (int)standard_36_deck::Suits::Spades);
	suit->addItem(tr("Heart"), (int)standard_36_deck::Suits::Hearts);
	suit->addItem(tr("Clubs"), (int)standard_36_deck::Suits::Clubs);
}

void GuiCardSelector::PopulateRanks() {
	rank->addItem(tr("Any rank"), (int)-1);
	rank->addItem(tr("Six"), (int)standard_36_deck::Ranks::Six);
	rank->addItem(tr("Seven"), (int)standard_36_deck::Ranks::Seven);
	rank->addItem(tr("Eight"), (int)standard_36_deck::Ranks::Eight);
	rank->addItem(tr("Nine"), (int)standard_36_deck::Ranks::Nine);
	rank->addItem(tr("Ten"), (int)standard_36_deck::Ranks::Ten);
	rank->addItem(tr("Jack"), (int)standard_36_deck::Ranks::Jack);
	rank->addItem(tr("Queen"), (int)standard_36_deck::Ranks::Queen);
	rank->addItem(tr("King"), (int)standard_36_deck::Ranks::King);
	rank->addItem(tr("Ace"), (int)standard_36_deck::Ranks::Ace);
}

void GuiCardSelector::CreateLayout() {
	auto layout = new QVBoxLayout();
	layout->addWidget(suit);
	layout->addWidget(rank);
	layout->addWidget(inverse);

	QPushButton *btn = new QPushButton(tr("Remove"));
	layout->addWidget(btn);
	QObject::connect(btn, &QPushButton::clicked, this, &GuiCardSelector::DeleteClicked);

	auto frame = new QFrame();
	frame->setLayout(layout);
	frame->setFrameStyle(QFrame::StyledPanel);

	setLayout(new QGridLayout());
	this->layout()->addWidget(frame);
}

CardSelector GuiCardSelector::GetSelector() const {
	int suitData = suit->currentData().toInt();
	int rankData = rank->currentData().toInt();

	bool suitSelected = suitData != -1;
	bool rankSelected = rankData != -1;
	bool isStraight = !inverse->isChecked();

	if (suitSelected && rankSelected) {
		return CardSelector(suitData, rankData, isStraight);
	} else if (suitSelected) {
		return CardSelector(Card::Suit(suitData), isStraight);
	} else if (rankSelected) {
		return CardSelector(Card::Rank(rankData), isStraight);
	} else {
		throw std::runtime_error("No suit or rank selected");
	}
}

<commit_msg>Adedd a helper for populating QComboBox'es<commit_after>#include "card_selector.h"
#include <QLayout>
#include <QVBoxLayout>
#include <cards/standard-36-deck.h>
#include <QPushButton>
#include <type_traits>
#include <exception>

#include <QFrame>

template<class T>
typename std::enable_if<std::is_same<T, QComboBox>::value>::type SelectData(T* comboBox, int data) {
	int index = comboBox->findData(data);
	if (index == -1)
		throw std::runtime_error("Unknown data");
	comboBox->setCurrentIndex(index);
}

GuiCardSelector::GuiCardSelector(int suit, int rank, bool inversed, QWidget* parent) : QWidget(parent) {
	CreateElements();
	PopulateSuits();
	PopulateRanks();
	CreateLayout();

	SelectData(this->suit, suit);
	SelectData(this->rank, rank);
	inverse->setChecked(inversed);
}

void GuiCardSelector::CreateElements() {
	suit = new QComboBox();
	rank = new QComboBox();
	inverse = new QCheckBox(tr("Inverse"));
}

class Populater {
public:
	Populater(QComboBox* box) : box(box) {}
	void Add(const QString& title, int value) {
		box->addItem(title, value);
	}
private:
	QComboBox* box;
};

void GuiCardSelector::PopulateSuits() {
	Populater p(suit);
	p.Add(tr("Any suit"), -1);
	p.Add(tr("Diamond"), standard_36_deck::Suits::Diamonds);
	p.Add(tr("Spade"), standard_36_deck::Suits::Spades);
	p.Add(tr("Heart"), standard_36_deck::Suits::Hearts);
	p.Add(tr("Clubs"), standard_36_deck::Suits::Clubs);
}

void GuiCardSelector::PopulateRanks() {
	Populater p(rank);
	p.Add(tr("Any rank"), -1);
	p.Add(tr("Six"), standard_36_deck::Ranks::Six);
	p.Add(tr("Seven"), standard_36_deck::Ranks::Seven);
	p.Add(tr("Eight"), standard_36_deck::Ranks::Eight);
	p.Add(tr("Nine"), standard_36_deck::Ranks::Nine);
	p.Add(tr("Ten"), standard_36_deck::Ranks::Ten);
	p.Add(tr("Jack"), standard_36_deck::Ranks::Jack);
	p.Add(tr("Queen"), standard_36_deck::Ranks::Queen);
	p.Add(tr("King"), standard_36_deck::Ranks::King);
	p.Add(tr("Ace"), standard_36_deck::Ranks::Ace);
}

void GuiCardSelector::CreateLayout() {
	auto layout = new QVBoxLayout();
	layout->addWidget(suit);
	layout->addWidget(rank);
	layout->addWidget(inverse);

	QPushButton *btn = new QPushButton(tr("Remove"));
	layout->addWidget(btn);
	QObject::connect(btn, &QPushButton::clicked, this, &GuiCardSelector::DeleteClicked);

	auto frame = new QFrame();
	frame->setLayout(layout);
	frame->setFrameStyle(QFrame::StyledPanel);

	setLayout(new QGridLayout());
	this->layout()->addWidget(frame);
}

CardSelector GuiCardSelector::GetSelector() const {
	int suitData = suit->currentData().toInt();
	int rankData = rank->currentData().toInt();

	bool suitSelected = suitData != -1;
	bool rankSelected = rankData != -1;
	bool isStraight = !inverse->isChecked();

	if (suitSelected && rankSelected) {
		return CardSelector(suitData, rankData, isStraight);
	} else if (suitSelected) {
		return CardSelector(Card::Suit(suitData), isStraight);
	} else if (rankSelected) {
		return CardSelector(Card::Rank(rankData), isStraight);
	} else {
		throw std::runtime_error("No suit or rank selected");
	}
}

<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  winURLLoader.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "winURLLoader.h"
#include "Core/String/StringConverter.h"
#include "IO/Stream/MemoryStream.h"
#define VC_EXTRALEAN (1)
#define WIN32_LEAN_AND_MEAN (1)
#include <Windows.h>
#include <WinHttp.h>

namespace Oryol {
namespace _priv {

const std::chrono::seconds winURLLoader::connectionMaxAge{10};

//------------------------------------------------------------------------------
winURLLoader::winURLLoader() :
contentTypeString("Content-Type")
{
    this->hSession = WinHttpOpen(NULL,      // pwszUserAgent
                                 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,     // dwAccessType
                                 WINHTTP_NO_PROXY_NAME, // pwszProxyName
                                 WINHTTP_NO_PROXY_BYPASS,   // pwszProxyByPass
                                 0);        // dwFlags
    o_assert(NULL != this->hSession);
}

//------------------------------------------------------------------------------
winURLLoader::~winURLLoader() {
    o_assert(NULL != this->hSession);
    // close remaining connections
    for (const auto& kvp : this->connections) {
        WinHttpCloseHandle(kvp.Value().hConnection);
    }
    this->connections.Clear();
    WinHttpCloseHandle(this->hSession);
    this->hSession = NULL;
}

//------------------------------------------------------------------------------
void
winURLLoader::doWork() {
    while (!this->requestQueue.Empty()) {
        Ptr<HTTPProtocol::HTTPRequest> req = this->requestQueue.Dequeue();
        if (!baseURLLoader::handleCancelled(req)) {
            this->doOneRequest(req);

            // transfer result to embedded ioRequest and set to handled
            auto ioReq = req->GetIoRequest();
            if (ioReq) {
                auto httpResponse = req->GetResponse();
                ioReq->SetStatus(httpResponse->GetStatus());
                ioReq->SetStream(httpResponse->GetBody());
                ioReq->SetErrorDesc(httpResponse->GetErrorDesc());
                ioReq->SetHandled();
            }
            req->SetHandled();
        }
    }
    this->garbageCollectConnections();
}

//------------------------------------------------------------------------------
void
winURLLoader::doOneRequest(const Ptr<HTTPProtocol::HTTPRequest>& req) {
    Log::Info("winURLLoader::doOneRequest() start: %s\n", req->GetURL().AsCStr());

    // obtain a connection
    HINTERNET hConn = this->obtainConnection(req->GetURL());
    if (NULL != hConn) {
        WideString method(HTTPMethod::ToWideString(req->GetMethod()));
        WideString path(StringConverter::UTF8ToWide(req->GetURL().PathToEnd()));

        // setup an HTTP request
        HINTERNET hRequest = WinHttpOpenRequest(
            hConn,              // hConnect
            method.AsCStr(),    // pwszVerb
            path.AsCStr(),      // pwszObjectName
            NULL,               // pwszVersion (NULL == HTTP/1.1)
            WINHTTP_NO_REFERER, // pwszReferrer
            WINHTTP_DEFAULT_ACCEPT_TYPES,   // pwszAcceptTypes
            WINHTTP_FLAG_ESCAPE_PERCENT);   // dwFlags
        if (NULL != hRequest) {

            // add request headers to the request
            if (!req->GetRequestHeaders().Empty()) {
                for (const auto& kvp : req->GetRequestHeaders()) {
                    this->stringBuilder.Clear();
                    this->stringBuilder.Append(kvp.Key());
                    this->stringBuilder.Append(": ");
                    this->stringBuilder.Append(kvp.Value());
                    this->stringBuilder.Append("\r\n");
                }

                // check if we need to add a Content-Type field:
                if (req->GetBody().isValid() && req->GetBody()->GetContentType().IsValid()) {
                    this->stringBuilder.Append("Content-Type: ");
                    this->stringBuilder.Append(req->GetBody()->GetContentType().AsCStr());
                    this->stringBuilder.Append("\r\n");
                }

                // remove last CRLF
                this->stringBuilder.PopBack();
                this->stringBuilder.PopBack();
                WideString reqHeaders(StringConverter::UTF8ToWide(this->stringBuilder.GetString()));
                BOOL headerResult = WinHttpAddRequestHeaders(
                    hRequest,
                    reqHeaders.AsCStr(),
                    reqHeaders.Length(),
                    WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE);
                o_assert(headerResult);
            }

            // do we have body-data?
            const uint8* bodyDataPtr = WINHTTP_NO_REQUEST_DATA;
            int32 bodySize = 0;
            if (req->GetBody().isValid()) {
                const Ptr<Stream>& bodyStream = req->GetBody();
                bodySize = bodyStream->Size();
                o_assert(bodySize > 0);
                bodyStream->Open(OpenMode::ReadOnly);
                bodyDataPtr = bodyStream->MapRead(nullptr);
            }

            // create a response object, no matter whether the
            // send fails or not
            Ptr<HTTPProtocol::HTTPResponse> httpResponse = HTTPProtocol::HTTPResponse::Create();
            req->SetResponse(httpResponse);

            // send the request
            BOOL sendResult = WinHttpSendRequest(
                hRequest,                           // hRequest
                WINHTTP_NO_ADDITIONAL_HEADERS,      // pwszHeaders
                0,                                  // dwHeadersLength
                (LPVOID) bodyDataPtr,               // lpOptional
                bodySize,                           // dwOptionalLength
                0,                                  // dwTotoalLength
                0);                                 // dwContext
            if (sendResult) {
                // receive and process response
                BOOL recvResult = WinHttpReceiveResponse(hRequest, NULL);
                if (recvResult) {
                    // query the HTTP status code
                    DWORD dwStatusCode = 0;
                    DWORD dwTemp = sizeof(dwStatusCode);
                    WinHttpQueryHeaders(
                        hRequest,
                        WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
                        NULL,
                        &dwStatusCode,
                        &dwTemp,
                        NULL);
                    httpResponse->SetStatus((IOStatus::Code) dwStatusCode);

                    // query the response headers required data size
                    DWORD dwSize = 0;
                    WinHttpQueryHeaders(hRequest,
                                        WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                        WINHTTP_HEADER_NAME_BY_INDEX,
                                        NULL,
                                        &dwSize,
                                        WINHTTP_NO_HEADER_INDEX);
                    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                        // and get the response headers
                        LPVOID headerBuffer = Memory::Alloc(dwSize);
                        BOOL headerResult = WinHttpQueryHeaders(
                            hRequest,
                            WINHTTP_QUERY_RAW_HEADERS_CRLF,
                            WINHTTP_HEADER_NAME_BY_INDEX,
                            headerBuffer,
                            &dwSize,
                            WINHTTP_NO_HEADER_INDEX);
                        o_assert(headerResult);

                        // convert from wide and split the header fields
                        this->stringBuilder.Set(StringConverter::WideToUTF8((const wchar_t*) headerBuffer, dwSize / sizeof(wchar_t)));
                        Memory::Free(headerBuffer);
                        Array<String> tokens;
                        this->stringBuilder.Tokenize("\r\n", tokens);
                        Map<String, String> fields;
                        fields.Reserve(tokens.Size());
                        for (const String& str : tokens) {
                            const int32 colonIndex = StringBuilder::FindFirstOf(str.AsCStr(), 0, EndOfString, ":");
                            if (colonIndex != InvalidIndex) {
                                String key(str.AsCStr(), 0, colonIndex);
                                String value(str.AsCStr(), colonIndex+2, EndOfString);
                                fields.Add(key, value);
                            }
                        }
                        httpResponse->SetResponseHeaders(fields);
                    }
                    else {
                        Log::Warn("winURLLoader: failed to extract response header fields!\n");
                    }

                    // extract body data
                    Ptr<MemoryStream> responseBodyStream = MemoryStream::Create();
                    responseBodyStream->SetURL(req->GetURL());
                    responseBodyStream->Open(OpenMode::WriteOnly);
                    DWORD bytesToRead = 0;
                    do {
                        // how much data available?
                        BOOL queryDataResult = WinHttpQueryDataAvailable(hRequest, &bytesToRead);
                        o_assert(queryDataResult);
                        if (dwSize > 0) {
                            uint8* dstPtr = responseBodyStream->MapWrite(bytesToRead);
                            o_assert(nullptr != dstPtr);
                            DWORD bytesRead = 0;
                            BOOL readDataResult = WinHttpReadData(hRequest, dstPtr, bytesToRead, &bytesRead);
                            o_assert(readDataResult);
                            o_assert(bytesRead == bytesToRead);
                            responseBodyStream->UnmapWrite();
                        }
                    }
                    while (bytesToRead > 0);
                    responseBodyStream->Close();

                    // extract the Content-Type response header field and set on responseBodyStream
                    if (httpResponse->GetResponseHeaders().Contains(this->contentTypeString)) {
                        ContentType contentType(httpResponse->GetResponseHeaders()[this->contentTypeString]);
                        responseBodyStream->SetContentType(contentType);
                    }

                    // ...and finally set the responseBodyStream on the httpResponse
                    httpResponse->SetBody(responseBodyStream);

                    // @todo: write error desc to httpResponse if something went wrong
                }
                else {
                    Log::Warn("winURLLoader: WinHttpReceiveResponse() failed for '%s'!\n", req->GetURL().AsCStr());
                }
            }
            else {
                /// @todo: better error reporting!
                Log::Warn("winURLLoader: WinHttpSendRequest() failed for '%s'\n", req->GetURL().AsCStr());
            }

            // unmap the body data if necessary
            if (req->GetBody().isValid()) {
                req->GetBody()->Close();
            }

            // close the request object
            WinHttpCloseHandle(hRequest);
        }
        else {
            Log::Warn("winURLLoader: WinHttpOpenRequest() failed for '%s'\n", req->GetURL().AsCStr());
        }
    }
    Log::Info("winURLLoader::doOneRequest() end: %s\n", req->GetURL().AsCStr());
}

//------------------------------------------------------------------------------
HINTERNET
winURLLoader::obtainConnection(const URL& url) {
    o_assert(NULL != this->hSession);
    const String hostAndPort = url.HostAndPort();
    if (this->connections.Contains(hostAndPort)) {
        // connection was already established, refresh the timestamp
        // and return the connection
        connection& con = this->connections[hostAndPort];
        con.timeStamp = std::chrono::steady_clock::now();
        return con.hConnection;
    }
    else {
        // new connection
        connection con;
        const WideString host = StringConverter::UTF8ToWide(url.Host());
        const String portString = url.Port();
        INTERNET_PORT port = INTERNET_DEFAULT_HTTP_PORT;
        if (!portString.Empty()) {
            port = StringConverter::FromString<int16>(portString);
        }
        con.hConnection = WinHttpConnect(this->hSession,        // hSession
                                          host.AsCStr(),        // pswzServerName
                                          port,                 // nServerPort
                                          0);                   // dwReserved
        if (NULL != con.hConnection) {
            con.timeStamp = std::chrono::steady_clock::now();
            this->connections.Add(hostAndPort, con);
            return con.hConnection;
        }
        else {
            Log::Warn("winURLLoader: failed to connect to '%s'\n", hostAndPort.AsCStr());
            return NULL;
        }
    }
}

//------------------------------------------------------------------------------
void
winURLLoader::garbageCollectConnections() {
    std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
    for (int32 i = this->connections.Size() - 1; i >= 0; i--) {
        const String key = this->connections.KeyAtIndex(i);
        const connection con = this->connections.ValueAtIndex(i);
        std::chrono::seconds age = std::chrono::duration_cast<std::chrono::seconds>(curTime - con.timeStamp);
        if (age > connectionMaxAge) {
            o_assert(NULL != con.hConnection);
            WinHttpCloseHandle(con.hConnection);
            this->connections.EraseIndex(i);
        }
    }
}

} // namespace _priv
} // namespace Oryol
<commit_msg>blind Windows compile fixes<commit_after>//------------------------------------------------------------------------------
//  winURLLoader.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "winURLLoader.h"
#include "Core/String/StringConverter.h"
#include "IO/Stream/MemoryStream.h"
#define VC_EXTRALEAN (1)
#define WIN32_LEAN_AND_MEAN (1)
#include <Windows.h>
#include <WinHttp.h>

namespace Oryol {
namespace _priv {

const std::chrono::seconds winURLLoader::connectionMaxAge{10};

//------------------------------------------------------------------------------
winURLLoader::winURLLoader() :
contentTypeString("Content-Type")
{
    this->hSession = WinHttpOpen(NULL,      // pwszUserAgent
                                 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,     // dwAccessType
                                 WINHTTP_NO_PROXY_NAME, // pwszProxyName
                                 WINHTTP_NO_PROXY_BYPASS,   // pwszProxyByPass
                                 0);        // dwFlags
    o_assert(NULL != this->hSession);
}

//------------------------------------------------------------------------------
winURLLoader::~winURLLoader() {
    o_assert(NULL != this->hSession);
    // close remaining connections
    for (const auto& kvp : this->connections) {
        WinHttpCloseHandle(kvp.Value().hConnection);
    }
    this->connections.Clear();
    WinHttpCloseHandle(this->hSession);
    this->hSession = NULL;
}

//------------------------------------------------------------------------------
void
winURLLoader::doWork() {
    while (!this->requestQueue.Empty()) {
        Ptr<HTTPProtocol::HTTPRequest> req = this->requestQueue.Dequeue();
        if (!baseURLLoader::handleCancelled(req)) {
            this->doOneRequest(req);

            // transfer result to embedded ioRequest and set to handled
            auto ioReq = req->IoRequest;
            if (ioReq) {
                auto httpResponse = req->Response;
                ioReq->Status = httpResponse->Status;
                ioReq->Data = httpResponse->Body;
                ioReq->ErrorDesc = httpResponse->ErrorDesc;
                ioReq->SetHandled();
            }
            req->SetHandled();
        }
    }
    this->garbageCollectConnections();
}

//------------------------------------------------------------------------------
void
winURLLoader::doOneRequest(const Ptr<HTTPProtocol::HTTPRequest>& req) {
    Log::Info("winURLLoader::doOneRequest() start: %s\n", req->Url.AsCStr());

    // obtain a connection
    HINTERNET hConn = this->obtainConnection(req->Url);
    if (NULL != hConn) {
        WideString method(HTTPMethod::ToWideString(req->Method));
        WideString path(StringConverter::UTF8ToWide(req->Url.PathToEnd()));

        // setup an HTTP request
        HINTERNET hRequest = WinHttpOpenRequest(
            hConn,              // hConnect
            method.AsCStr(),    // pwszVerb
            path.AsCStr(),      // pwszObjectName
            NULL,               // pwszVersion (NULL == HTTP/1.1)
            WINHTTP_NO_REFERER, // pwszReferrer
            WINHTTP_DEFAULT_ACCEPT_TYPES,   // pwszAcceptTypes
            WINHTTP_FLAG_ESCAPE_PERCENT);   // dwFlags
        if (NULL != hRequest) {

            // add request headers to the request
            if (!req->RequestHeaders.Empty()) {
                for (const auto& kvp : req->RequestHeaders) {
                    this->stringBuilder.Clear();
                    this->stringBuilder.Append(kvp.Key());
                    this->stringBuilder.Append(": ");
                    this->stringBuilder.Append(kvp.Value());
                    this->stringBuilder.Append("\r\n");
                }

                // check if we need to add a Content-Type field:
                if (req->Body.isValid() && req->Body->GetContentType().IsValid()) {
                    this->stringBuilder.Append("Content-Type: ");
                    this->stringBuilder.Append(req->Body->GetContentType().AsCStr());
                    this->stringBuilder.Append("\r\n");
                }

                // remove last CRLF
                this->stringBuilder.PopBack();
                this->stringBuilder.PopBack();
                WideString reqHeaders(StringConverter::UTF8ToWide(this->stringBuilder.GetString()));
                BOOL headerResult = WinHttpAddRequestHeaders(
                    hRequest,
                    reqHeaders.AsCStr(),
                    reqHeaders.Length(),
                    WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE);
                o_assert(headerResult);
            }

            // do we have body-data?
            const uint8* bodyDataPtr = WINHTTP_NO_REQUEST_DATA;
            int32 bodySize = 0;
            if (req->Body.isValid()) {
                const Ptr<Stream>& bodyStream = req->Body;
                bodySize = bodyStream->Size();
                o_assert(bodySize > 0);
                bodyStream->Open(OpenMode::ReadOnly);
                bodyDataPtr = bodyStream->MapRead(nullptr);
            }

            // create a response object, no matter whether the
            // send fails or not
            Ptr<HTTPProtocol::HTTPResponse> httpResponse = HTTPProtocol::HTTPResponse::Create();
            req->SetResponse(httpResponse);

            // send the request
            BOOL sendResult = WinHttpSendRequest(
                hRequest,                           // hRequest
                WINHTTP_NO_ADDITIONAL_HEADERS,      // pwszHeaders
                0,                                  // dwHeadersLength
                (LPVOID) bodyDataPtr,               // lpOptional
                bodySize,                           // dwOptionalLength
                0,                                  // dwTotoalLength
                0);                                 // dwContext
            if (sendResult) {
                // receive and process response
                BOOL recvResult = WinHttpReceiveResponse(hRequest, NULL);
                if (recvResult) {
                    // query the HTTP status code
                    DWORD dwStatusCode = 0;
                    DWORD dwTemp = sizeof(dwStatusCode);
                    WinHttpQueryHeaders(
                        hRequest,
                        WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
                        NULL,
                        &dwStatusCode,
                        &dwTemp,
                        NULL);
                    httpResponse->Status = (IOStatus::Code) dwStatusCode;

                    // query the response headers required data size
                    DWORD dwSize = 0;
                    WinHttpQueryHeaders(hRequest,
                                        WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                        WINHTTP_HEADER_NAME_BY_INDEX,
                                        NULL,
                                        &dwSize,
                                        WINHTTP_NO_HEADER_INDEX);
                    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                        // and get the response headers
                        LPVOID headerBuffer = Memory::Alloc(dwSize);
                        BOOL headerResult = WinHttpQueryHeaders(
                            hRequest,
                            WINHTTP_QUERY_RAW_HEADERS_CRLF,
                            WINHTTP_HEADER_NAME_BY_INDEX,
                            headerBuffer,
                            &dwSize,
                            WINHTTP_NO_HEADER_INDEX);
                        o_assert(headerResult);

                        // convert from wide and split the header fields
                        this->stringBuilder.Set(StringConverter::WideToUTF8((const wchar_t*) headerBuffer, dwSize / sizeof(wchar_t)));
                        Memory::Free(headerBuffer);
                        Array<String> tokens;
                        this->stringBuilder.Tokenize("\r\n", tokens);
                        Map<String, String> fields;
                        fields.Reserve(tokens.Size());
                        for (const String& str : tokens) {
                            const int32 colonIndex = StringBuilder::FindFirstOf(str.AsCStr(), 0, EndOfString, ":");
                            if (colonIndex != InvalidIndex) {
                                String key(str.AsCStr(), 0, colonIndex);
                                String value(str.AsCStr(), colonIndex+2, EndOfString);
                                fields.Add(key, value);
                            }
                        }
                        httpResponse->ResponseHeaders = fields;
                    }
                    else {
                        Log::Warn("winURLLoader: failed to extract response header fields!\n");
                    }

                    // extract body data
                    Ptr<MemoryStream> responseBodyStream = MemoryStream::Create();
                    responseBodyStream->SetURL(req->GetURL());
                    responseBodyStream->Open(OpenMode::WriteOnly);
                    DWORD bytesToRead = 0;
                    do {
                        // how much data available?
                        BOOL queryDataResult = WinHttpQueryDataAvailable(hRequest, &bytesToRead);
                        o_assert(queryDataResult);
                        if (dwSize > 0) {
                            uint8* dstPtr = responseBodyStream->MapWrite(bytesToRead);
                            o_assert(nullptr != dstPtr);
                            DWORD bytesRead = 0;
                            BOOL readDataResult = WinHttpReadData(hRequest, dstPtr, bytesToRead, &bytesRead);
                            o_assert(readDataResult);
                            o_assert(bytesRead == bytesToRead);
                            responseBodyStream->UnmapWrite();
                        }
                    }
                    while (bytesToRead > 0);
                    responseBodyStream->Close();

                    // extract the Content-Type response header field and set on responseBodyStream
                    if (httpResponse->ResponseHeaders.Contains(this->contentTypeString)) {
                        ContentType contentType(httpResponse->ResponseHeaders[this->contentTypeString]);
                        responseBodyStream->SetContentType(contentType);
                    }

                    // ...and finally set the responseBodyStream on the httpResponse
                    httpResponse->Body = responseBodyStream;

                    // @todo: write error desc to httpResponse if something went wrong
                }
                else {
                    Log::Warn("winURLLoader: WinHttpReceiveResponse() failed for '%s'!\n", req->GetURL().AsCStr());
                }
            }
            else {
                /// @todo: better error reporting!
                Log::Warn("winURLLoader: WinHttpSendRequest() failed for '%s'\n", req->GetURL().AsCStr());
            }

            // unmap the body data if necessary
            if (req->Body.isValid()) {
                req->Body->Close();
            }

            // close the request object
            WinHttpCloseHandle(hRequest);
        }
        else {
            Log::Warn("winURLLoader: WinHttpOpenRequest() failed for '%s'\n", req->Url.AsCStr());
        }
    }
    Log::Info("winURLLoader::doOneRequest() end: %s\n", req->Url.AsCStr());
}

//------------------------------------------------------------------------------
HINTERNET
winURLLoader::obtainConnection(const URL& url) {
    o_assert(NULL != this->hSession);
    const String hostAndPort = url.HostAndPort();
    if (this->connections.Contains(hostAndPort)) {
        // connection was already established, refresh the timestamp
        // and return the connection
        connection& con = this->connections[hostAndPort];
        con.timeStamp = std::chrono::steady_clock::now();
        return con.hConnection;
    }
    else {
        // new connection
        connection con;
        const WideString host = StringConverter::UTF8ToWide(url.Host());
        const String portString = url.Port();
        INTERNET_PORT port = INTERNET_DEFAULT_HTTP_PORT;
        if (!portString.Empty()) {
            port = StringConverter::FromString<int16>(portString);
        }
        con.hConnection = WinHttpConnect(this->hSession,        // hSession
                                          host.AsCStr(),        // pswzServerName
                                          port,                 // nServerPort
                                          0);                   // dwReserved
        if (NULL != con.hConnection) {
            con.timeStamp = std::chrono::steady_clock::now();
            this->connections.Add(hostAndPort, con);
            return con.hConnection;
        }
        else {
            Log::Warn("winURLLoader: failed to connect to '%s'\n", hostAndPort.AsCStr());
            return NULL;
        }
    }
}

//------------------------------------------------------------------------------
void
winURLLoader::garbageCollectConnections() {
    std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
    for (int32 i = this->connections.Size() - 1; i >= 0; i--) {
        const String key = this->connections.KeyAtIndex(i);
        const connection con = this->connections.ValueAtIndex(i);
        std::chrono::seconds age = std::chrono::duration_cast<std::chrono::seconds>(curTime - con.timeStamp);
        if (age > connectionMaxAge) {
            o_assert(NULL != con.hConnection);
            WinHttpCloseHandle(con.hConnection);
            this->connections.EraseIndex(i);
        }
    }
}

} // namespace _priv
} // namespace Oryol

<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
#include <Eigen/LU>

/* Check that two column vectors are approximately equal upto permutations,
   by checking that the k-th power sums are equal for k = 1, ..., vec1.rows() */
template<typename VectorType>
void verify_is_approx_upto_permutation(const VectorType& vec1, const VectorType& vec2)
{
  typedef typename NumTraits<VectorType::Scalar>::Real RealScalar;

  VERIFY(vec1.cols() == 1);
  VERIFY(vec2.cols() == 1);
  VERIFY(vec1.rows() == vec2.rows());
  for (int k = 1; k <= vec1.rows(); ++k)
  {
    VERIFY_IS_APPROX(vec1.array().pow(RealScalar(k)).sum(), vec2.array().pow(RealScalar(k)).sum());
  }
}

template<typename MatrixType> void eigensolver(const MatrixType& m)
{
  /* this test covers the following files:
     ComplexEigenSolver.h, and indirectly ComplexSchur.h
  */
  int rows = m.rows();
  int cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;

  MatrixType a = MatrixType::Random(rows,cols);
  MatrixType symmA =  a.adjoint() * a;

  ComplexEigenSolver<MatrixType> ei0(symmA);
  VERIFY_IS_EQUAL(ei0.info(), Success);
  VERIFY_IS_APPROX(symmA * ei0.eigenvectors(), ei0.eigenvectors() * ei0.eigenvalues().asDiagonal());

  ComplexEigenSolver<MatrixType> ei1(a);
  VERIFY_IS_EQUAL(ei1.info(), Success);
  VERIFY_IS_APPROX(a * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
  // Note: If MatrixType is real then a.eigenvalues() uses EigenSolver and thus
  // another algorithm so results may differ slightly
  verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues());

  ComplexEigenSolver<MatrixType> eiNoEivecs(a, false);
  VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
  VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());

  // Regression test for issue #66
  MatrixType z = MatrixType::Zero(rows,cols);
  ComplexEigenSolver<MatrixType> eiz(z);
  VERIFY((eiz.eigenvalues().cwiseEqual(0)).all());

  MatrixType id = MatrixType::Identity(rows, cols);
  VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));

  if (rows > 1)
  {
    // Test matrix with NaN
    a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
    ComplexEigenSolver<MatrixType> eiNaN(a);
    VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
  }
}

template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
{
  ComplexEigenSolver<MatrixType> eig;
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
  VERIFY_RAISES_ASSERT(eig.eigenvalues());

  MatrixType a = MatrixType::Random(m.rows(),m.cols());
  eig.compute(a, false);
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
}

void test_eigensolver_complex()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
    CALL_SUBTEST_2( eigensolver(MatrixXcd(14,14)) );
    CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
    CALL_SUBTEST_4( eigensolver(Matrix3f()) );
  }

  CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
  CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(14,14)) );
  CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<std::complex<float>, 1, 1>()) );
  CALL_SUBTEST_4( eigensolver_verify_assert(Matrix3f()) );

  // Test problem size constructors
  CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf>(10));
}
<commit_msg>Fixed GCC compilation.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
#include <Eigen/LU>

/* Check that two column vectors are approximately equal upto permutations,
   by checking that the k-th power sums are equal for k = 1, ..., vec1.rows() */
template<typename VectorType>
void verify_is_approx_upto_permutation(const VectorType& vec1, const VectorType& vec2)
{
  typedef typename NumTraits<typename VectorType::Scalar>::Real RealScalar;

  VERIFY(vec1.cols() == 1);
  VERIFY(vec2.cols() == 1);
  VERIFY(vec1.rows() == vec2.rows());
  for (int k = 1; k <= vec1.rows(); ++k)
  {
    VERIFY_IS_APPROX(vec1.array().pow(RealScalar(k)).sum(), vec2.array().pow(RealScalar(k)).sum());
  }
}

template<typename MatrixType> void eigensolver(const MatrixType& m)
{
  /* this test covers the following files:
     ComplexEigenSolver.h, and indirectly ComplexSchur.h
  */
  int rows = m.rows();
  int cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;

  MatrixType a = MatrixType::Random(rows,cols);
  MatrixType symmA =  a.adjoint() * a;

  ComplexEigenSolver<MatrixType> ei0(symmA);
  VERIFY_IS_EQUAL(ei0.info(), Success);
  VERIFY_IS_APPROX(symmA * ei0.eigenvectors(), ei0.eigenvectors() * ei0.eigenvalues().asDiagonal());

  ComplexEigenSolver<MatrixType> ei1(a);
  VERIFY_IS_EQUAL(ei1.info(), Success);
  VERIFY_IS_APPROX(a * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
  // Note: If MatrixType is real then a.eigenvalues() uses EigenSolver and thus
  // another algorithm so results may differ slightly
  verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues());

  ComplexEigenSolver<MatrixType> eiNoEivecs(a, false);
  VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
  VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());

  // Regression test for issue #66
  MatrixType z = MatrixType::Zero(rows,cols);
  ComplexEigenSolver<MatrixType> eiz(z);
  VERIFY((eiz.eigenvalues().cwiseEqual(0)).all());

  MatrixType id = MatrixType::Identity(rows, cols);
  VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));

  if (rows > 1)
  {
    // Test matrix with NaN
    a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
    ComplexEigenSolver<MatrixType> eiNaN(a);
    VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
  }
}

template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
{
  ComplexEigenSolver<MatrixType> eig;
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
  VERIFY_RAISES_ASSERT(eig.eigenvalues());

  MatrixType a = MatrixType::Random(m.rows(),m.cols());
  eig.compute(a, false);
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
}

void test_eigensolver_complex()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
    CALL_SUBTEST_2( eigensolver(MatrixXcd(14,14)) );
    CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
    CALL_SUBTEST_4( eigensolver(Matrix3f()) );
  }

  CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
  CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(14,14)) );
  CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<std::complex<float>, 1, 1>()) );
  CALL_SUBTEST_4( eigensolver_verify_assert(Matrix3f()) );

  // Test problem size constructors
  CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf>(10));
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>

template<typename MatrixType> void eigensolver(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  /* this test covers the following files:
     EigenSolver.h
  */
  Index rows = m.rows();
  Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;

  MatrixType a = MatrixType::Random(rows,cols);
  MatrixType a1 = MatrixType::Random(rows,cols);
  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;

  EigenSolver<MatrixType> ei0(symmA);
  VERIFY_IS_EQUAL(ei0.info(), Success);
  VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix());
  VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()),
    (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal()));

  EigenSolver<MatrixType> ei1(a);
  VERIFY_IS_EQUAL(ei1.info(), Success);
  VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
  VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
                   ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
  VERIFY_IS_APPROX(ei1.eigenvectors().colwise().norm(), RealVectorType::Ones(rows).transpose());
  VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());

  EigenSolver<MatrixType> ei2;
  ei2.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
  VERIFY_IS_EQUAL(ei2.info(), Success);
  VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
  VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
  if (rows > 2) {
    ei2.setMaxIterations(1).compute(a);
    VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
    VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
  }

  EigenSolver<MatrixType> eiNoEivecs(a, false);
  VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
  VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
  VERIFY_IS_APPROX(ei1.pseudoEigenvalueMatrix(), eiNoEivecs.pseudoEigenvalueMatrix());

  MatrixType id = MatrixType::Identity(rows, cols);
  VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));

  if (rows > 2)
  {
    // Test matrix with NaN
    a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
    EigenSolver<MatrixType> eiNaN(a);
    VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
  }
}

template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
{
  EigenSolver<MatrixType> eig;
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
  VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
  VERIFY_RAISES_ASSERT(eig.pseudoEigenvalueMatrix());
  VERIFY_RAISES_ASSERT(eig.eigenvalues());

  MatrixType a = MatrixType::Random(m.rows(),m.cols());
  eig.compute(a, false);
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
  VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
}

void test_eigensolver_generic()
{
  int s = 0;
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( eigensolver(Matrix4f()) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
    CALL_SUBTEST_2( eigensolver(MatrixXd(s,s)) );

    // some trivial but implementation-wise tricky cases
    CALL_SUBTEST_2( eigensolver(MatrixXd(1,1)) );
    CALL_SUBTEST_2( eigensolver(MatrixXd(2,2)) );
    CALL_SUBTEST_3( eigensolver(Matrix<double,1,1>()) );
    CALL_SUBTEST_4( eigensolver(Matrix2d()) );
  }

  CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4f()) );
  s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
  CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXd(s,s)) );
  CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<double,1,1>()) );
  CALL_SUBTEST_4( eigensolver_verify_assert(Matrix2d()) );

  // Test problem size constructors
  CALL_SUBTEST_5(EigenSolver<MatrixXf> tmp(s));

  // regression test for bug 410
  CALL_SUBTEST_2(
  {
     MatrixXd A(1,1);
     A(0,0) = std::sqrt(-1.);
     Eigen::EigenSolver<MatrixXd> solver(A);
     MatrixXd V(1, 1);
     V(0,0) = solver.eigenvectors()(0,0).real();
  }
  );

  // regression test for bug 793
#ifdef EIGEN_TEST_PART_2
  {
     MatrixXd a(3,3);
     a << 0,  0,  1,
          1,  1, 1,
          1, 1e+200,  1;
     Eigen::EigenSolver<MatrixXd> eig(a);
     VERIFY_IS_APPROX(a * eig.pseudoEigenvectors(), eig.pseudoEigenvectors() * eig.pseudoEigenvalueMatrix());
     VERIFY_IS_APPROX(a * eig.eigenvectors(), eig.eigenvectors() * eig.eigenvalues().asDiagonal());
  }
#endif

  TEST_SET_BUT_UNUSED_VARIABLE(s)
}
<commit_msg>Fix test: EigenSolver on 1x1 matrix with NaN sets info to NumericalIssue. This was changed in 7aaf133083b7.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>

template<typename MatrixType> void eigensolver(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  /* this test covers the following files:
     EigenSolver.h
  */
  Index rows = m.rows();
  Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;

  MatrixType a = MatrixType::Random(rows,cols);
  MatrixType a1 = MatrixType::Random(rows,cols);
  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;

  EigenSolver<MatrixType> ei0(symmA);
  VERIFY_IS_EQUAL(ei0.info(), Success);
  VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix());
  VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()),
    (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal()));

  EigenSolver<MatrixType> ei1(a);
  VERIFY_IS_EQUAL(ei1.info(), Success);
  VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
  VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
                   ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
  VERIFY_IS_APPROX(ei1.eigenvectors().colwise().norm(), RealVectorType::Ones(rows).transpose());
  VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());

  EigenSolver<MatrixType> ei2;
  ei2.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
  VERIFY_IS_EQUAL(ei2.info(), Success);
  VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
  VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
  if (rows > 2) {
    ei2.setMaxIterations(1).compute(a);
    VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
    VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
  }

  EigenSolver<MatrixType> eiNoEivecs(a, false);
  VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
  VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
  VERIFY_IS_APPROX(ei1.pseudoEigenvalueMatrix(), eiNoEivecs.pseudoEigenvalueMatrix());

  MatrixType id = MatrixType::Identity(rows, cols);
  VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));

  if (rows > 2)
  {
    // Test matrix with NaN
    a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
    EigenSolver<MatrixType> eiNaN(a);
    VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
  }
}

template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
{
  EigenSolver<MatrixType> eig;
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
  VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
  VERIFY_RAISES_ASSERT(eig.pseudoEigenvalueMatrix());
  VERIFY_RAISES_ASSERT(eig.eigenvalues());

  MatrixType a = MatrixType::Random(m.rows(),m.cols());
  eig.compute(a, false);
  VERIFY_RAISES_ASSERT(eig.eigenvectors());
  VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
}

void test_eigensolver_generic()
{
  int s = 0;
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( eigensolver(Matrix4f()) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
    CALL_SUBTEST_2( eigensolver(MatrixXd(s,s)) );

    // some trivial but implementation-wise tricky cases
    CALL_SUBTEST_2( eigensolver(MatrixXd(1,1)) );
    CALL_SUBTEST_2( eigensolver(MatrixXd(2,2)) );
    CALL_SUBTEST_3( eigensolver(Matrix<double,1,1>()) );
    CALL_SUBTEST_4( eigensolver(Matrix2d()) );
  }

  CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4f()) );
  s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
  CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXd(s,s)) );
  CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<double,1,1>()) );
  CALL_SUBTEST_4( eigensolver_verify_assert(Matrix2d()) );

  // Test problem size constructors
  CALL_SUBTEST_5(EigenSolver<MatrixXf> tmp(s));

  // regression test for bug 410
  CALL_SUBTEST_2(
  {
     MatrixXd A(1,1);
     A(0,0) = std::sqrt(-1.); // is Not-a-Number
     Eigen::EigenSolver<MatrixXd> solver(A);
     VERIFY_IS_EQUAL(solver.info(), NumericalIssue);
  }
  );

  // regression test for bug 793
#ifdef EIGEN_TEST_PART_2
  {
     MatrixXd a(3,3);
     a << 0,  0,  1,
          1,  1, 1,
          1, 1e+200,  1;
     Eigen::EigenSolver<MatrixXd> eig(a);
     VERIFY_IS_APPROX(a * eig.pseudoEigenvectors(), eig.pseudoEigenvectors() * eig.pseudoEigenvalueMatrix());
     VERIFY_IS_APPROX(a * eig.eigenvectors(), eig.eigenvectors() * eig.eigenvalues().asDiagonal());
  }
#endif

  TEST_SET_BUT_UNUSED_VARIABLE(s)
}
<|endoftext|>


<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    mainwindow.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra 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.

    Kleopatra 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

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "mainwindow.h"
#include "mainwindow_p.h"

#include "models/keylistmodel.h"
#include "models/keylistsortfilterproxymodel.h"
#include "controllers/keylistcontroller.h"
#include "certificateinfowidgetimpl.h"

#include <kleo/cryptobackendfactory.h>
#include <kleo/keylistjob.h>

#include <qgpgme/eventloopinteractor.h>

#include <KDialog>
#include <KLocale>

#include <QAction>
#include <QApplication>
#include <QDebug>
#include <QLineEdit>
#include <QMenuBar>
#include <QModelIndex>
#include <QStatusBar>
#include <QStringList>
#include <QTimer>
#include <QTreeView>
#include <QVBoxLayout>

class MainWindow::Private {
    friend class ::MainWindow;
    MainWindow * const q;
private:
    explicit Private( MainWindow * qq ) : q( qq ), model( 0 ), relay( 0 ) {}
    ~Private() {}

    void setupMenu();
    void listKeys();
    void startKeyListing( const char* backend );
    void viewDetails( const GpgME::Key& key );
    void viewDetails( const QModelIndex& idx );

private:
    Kleo::AbstractKeyListModel * model;
    Kleo::KeyListController controller;
    ::Relay* relay;
    ::StatusBarUpdater* statusBarUpdater;
};

void MainWindow::Private::setupMenu()
{
    QMenu* const fileMenu = q->menuBar()->addMenu( i18n("&File") );
    QAction* const quitAction = fileMenu->addAction( i18n("Quit"), qApp, SLOT( quit() ) );
    quitAction->setShortcut( Qt::CTRL + Qt::Key_Q );
    QMenu* const viewMenu = q->menuBar()->addMenu( i18n("&View") );
    QAction* const refreshAction = viewMenu->addAction( i18n("Refresh Key List"), q, SLOT( listKeys() ) );
    refreshAction->setShortcut( Qt::Key_F5 );
}

void MainWindow::Private::viewDetails( const QModelIndex& idx ) {
    viewDetails( model->key( idx ) );
}

void MainWindow::Private::viewDetails( const GpgME::Key& key ) {
    if ( key.isNull() )
        return;

    KDialog* dialog = new KDialog( q );
    dialog->setObjectName( "dialog" );
    dialog->setModal( false );
    dialog->setWindowTitle( i18n("Additional Information for Certificate") );
    dialog->setButtons( KDialog::Close );
    dialog->setDefaultButton( KDialog::Close );
    dialog->setAttribute( Qt::WA_DeleteOnClose );
    CertificateInfoWidgetImpl* top = new CertificateInfoWidgetImpl( key, /*isRemote=*/false, dialog );
    dialog->setMainWidget( top );
#if 0
    q->connect( top, SIGNAL( requestCertificateDownload( QString, QString ) ),
                SLOT( slotStartCertificateDownload( QString, QString ) ) );
#endif
    dialog->show();
}

void MainWindow::Private::startKeyListing( const char* backend )
{
    Kleo::KeyListJob *keylisting = Kleo::CryptoBackendFactory::instance()->protocol( backend )->keyListJob();
    QObject::connect( keylisting, SIGNAL( result( GpgME::KeyListResult ) ),
             relay, SLOT( keyListingDone( GpgME::KeyListResult ) ) );
    QObject::connect( keylisting, SIGNAL( nextKey( GpgME::Key ) ),
             relay, SLOT( nextKey( GpgME::Key ) ) );
    statusBarUpdater->registerJob( keylisting );
    keylisting->start( QStringList() );
}

MainWindow::MainWindow( QWidget* parent, Qt::WindowFlags flags ) : QMainWindow( parent, flags ), d( new MainWindow::Private( this ) ) {
    setWindowTitle( i18n("Kleopatra") );

    QWidget* flatWidget = new QWidget( parent );
    QVBoxLayout* flatLayout = new QVBoxLayout( flatWidget );
    QLineEdit* flatLE = new QLineEdit;
    QTreeView* flatListView = new QTreeView;
    flatListView->setRootIsDecorated( false );
    flatListView->setSortingEnabled( true );
    flatListView->sortByColumn( Kleo::AbstractKeyListModel::Fingerprint, Qt::AscendingOrder );
    connect( flatListView, SIGNAL( doubleClicked( QModelIndex ) ),
             SLOT( viewDetails( QModelIndex ) ) );
    flatLayout->addWidget( flatLE );
    flatLayout->addWidget( flatListView );

    Kleo::KeyListSortFilterProxyModel* flatProxy = new Kleo::KeyListSortFilterProxyModel;
    connect( flatLE, SIGNAL( textChanged( QString ) ), flatProxy, SLOT( setFilterFixedString( QString ) ) );

    setCentralWidget( flatWidget );

    d->relay = new ::Relay( this );
    d->statusBarUpdater = new ::StatusBarUpdater( statusBar(), this );

    if ( d->model = Kleo::AbstractKeyListModel::createFlatKeyListModel( flatListView ) ) {
        connect( d->relay, SIGNAL( nextKeys( std::vector<GpgME::Key> ) ), d->model, SLOT( addKeys( std::vector<GpgME::Key> ) ) );
        flatProxy->setSourceModel( d->model );
        flatListView->setModel( flatProxy );
    }

    d->setupMenu();
    QTimer* keyListTimer = new QTimer( this );
    connect( keyListTimer, SIGNAL( timeout() ), SLOT( listKeys() ) );
    keyListTimer->setInterval( 30 * 1000 );
    keyListTimer->start();
    QTimer::singleShot( 0, this, SLOT( listKeys() ) );
}

MainWindow::~MainWindow() {
    delete d;
}

void MainWindow::Private::listKeys() {
    startKeyListing( "openpgp" );
    startKeyListing( "smime" );
}

TrayIconListener::TrayIconListener( QWidget* mainWindow, QObject* parent ) : QObject( parent ), m_mainWindow( mainWindow )
{
    assert( m_mainWindow );
}

void TrayIconListener::activated( QSystemTrayIcon::ActivationReason reason )
{
    if ( reason != QSystemTrayIcon::Trigger )
        return;
    const bool visible = !m_mainWindow->isVisible();
    if ( visible ) {
        if ( m_prevGeometry.isValid() )
            m_mainWindow->setGeometry( m_prevGeometry );
        m_mainWindow->setVisible( true );
    } else {
        m_prevGeometry = m_mainWindow->geometry();
        m_mainWindow->setVisible( false );
    }
}

StatusBarUpdater::StatusBarUpdater( QStatusBar* bar, QObject* parent ) : QObject( parent ), m_bar( bar ), m_pendingJobs( 0 ) {
    assert( m_bar );
}

void StatusBarUpdater::registerJob( Kleo::KeyListJob* job ) {
    //TODO: handle errors
    connect( job, SIGNAL( result( GpgME::KeyListResult ) ),
             SLOT( keyListResult( GpgME::KeyListResult ) ) );
    ++m_pendingJobs;
    m_bar->showMessage( i18n("Fetching keys...") );
}

void StatusBarUpdater::keyListResult( const GpgME::KeyListResult& result ) {
    Q_UNUSED( result );
    --m_pendingJobs;
    assert( m_pendingJobs >= 0 );
    if ( m_pendingJobs == 0 )
        m_bar->clearMessage();
}

#include "mainwindow_p.moc"
#include "mainwindow.moc"
<commit_msg>more sane update interval<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    mainwindow.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra 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.

    Kleopatra 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

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "mainwindow.h"
#include "mainwindow_p.h"

#include "models/keylistmodel.h"
#include "models/keylistsortfilterproxymodel.h"
#include "controllers/keylistcontroller.h"
#include "certificateinfowidgetimpl.h"

#include <kleo/cryptobackendfactory.h>
#include <kleo/keylistjob.h>

#include <qgpgme/eventloopinteractor.h>

#include <KDialog>
#include <KLocale>

#include <QAction>
#include <QApplication>
#include <QDebug>
#include <QLineEdit>
#include <QMenuBar>
#include <QModelIndex>
#include <QStatusBar>
#include <QStringList>
#include <QTimer>
#include <QTreeView>
#include <QVBoxLayout>

class MainWindow::Private {
    friend class ::MainWindow;
    MainWindow * const q;
private:
    explicit Private( MainWindow * qq ) : q( qq ), model( 0 ), relay( 0 ) {}
    ~Private() {}

    void setupMenu();
    void listKeys();
    void startKeyListing( const char* backend );
    void viewDetails( const GpgME::Key& key );
    void viewDetails( const QModelIndex& idx );

private:
    Kleo::AbstractKeyListModel * model;
    Kleo::KeyListController controller;
    ::Relay* relay;
    ::StatusBarUpdater* statusBarUpdater;
};

void MainWindow::Private::setupMenu()
{
    QMenu* const fileMenu = q->menuBar()->addMenu( i18n("&File") );
    QAction* const quitAction = fileMenu->addAction( i18n("Quit"), qApp, SLOT( quit() ) );
    quitAction->setShortcut( Qt::CTRL + Qt::Key_Q );
    QMenu* const viewMenu = q->menuBar()->addMenu( i18n("&View") );
    QAction* const refreshAction = viewMenu->addAction( i18n("Refresh Key List"), q, SLOT( listKeys() ) );
    refreshAction->setShortcut( Qt::Key_F5 );
}

void MainWindow::Private::viewDetails( const QModelIndex& idx ) {
    viewDetails( model->key( idx ) );
}

void MainWindow::Private::viewDetails( const GpgME::Key& key ) {
    if ( key.isNull() )
        return;

    KDialog* dialog = new KDialog( q );
    dialog->setObjectName( "dialog" );
    dialog->setModal( false );
    dialog->setWindowTitle( i18n("Additional Information for Certificate") );
    dialog->setButtons( KDialog::Close );
    dialog->setDefaultButton( KDialog::Close );
    dialog->setAttribute( Qt::WA_DeleteOnClose );
    CertificateInfoWidgetImpl* top = new CertificateInfoWidgetImpl( key, /*isRemote=*/false, dialog );
    dialog->setMainWidget( top );
#if 0
    q->connect( top, SIGNAL( requestCertificateDownload( QString, QString ) ),
                SLOT( slotStartCertificateDownload( QString, QString ) ) );
#endif
    dialog->show();
}

void MainWindow::Private::startKeyListing( const char* backend )
{
    Kleo::KeyListJob *keylisting = Kleo::CryptoBackendFactory::instance()->protocol( backend )->keyListJob();
    QObject::connect( keylisting, SIGNAL( result( GpgME::KeyListResult ) ),
             relay, SLOT( keyListingDone( GpgME::KeyListResult ) ) );
    QObject::connect( keylisting, SIGNAL( nextKey( GpgME::Key ) ),
             relay, SLOT( nextKey( GpgME::Key ) ) );
    statusBarUpdater->registerJob( keylisting );
    keylisting->start( QStringList() );
}

MainWindow::MainWindow( QWidget* parent, Qt::WindowFlags flags ) : QMainWindow( parent, flags ), d( new MainWindow::Private( this ) ) {
    setWindowTitle( i18n("Kleopatra") );

    QWidget* flatWidget = new QWidget( parent );
    QVBoxLayout* flatLayout = new QVBoxLayout( flatWidget );
    QLineEdit* flatLE = new QLineEdit;
    QTreeView* flatListView = new QTreeView;
    flatListView->setRootIsDecorated( false );
    flatListView->setSortingEnabled( true );
    flatListView->sortByColumn( Kleo::AbstractKeyListModel::Fingerprint, Qt::AscendingOrder );
    connect( flatListView, SIGNAL( doubleClicked( QModelIndex ) ),
             SLOT( viewDetails( QModelIndex ) ) );
    flatLayout->addWidget( flatLE );
    flatLayout->addWidget( flatListView );

    Kleo::KeyListSortFilterProxyModel* flatProxy = new Kleo::KeyListSortFilterProxyModel;
    connect( flatLE, SIGNAL( textChanged( QString ) ), flatProxy, SLOT( setFilterFixedString( QString ) ) );

    setCentralWidget( flatWidget );

    d->relay = new ::Relay( this );
    d->statusBarUpdater = new ::StatusBarUpdater( statusBar(), this );

    if ( d->model = Kleo::AbstractKeyListModel::createFlatKeyListModel( flatListView ) ) {
        connect( d->relay, SIGNAL( nextKeys( std::vector<GpgME::Key> ) ), d->model, SLOT( addKeys( std::vector<GpgME::Key> ) ) );
        flatProxy->setSourceModel( d->model );
        flatListView->setModel( flatProxy );
    }

    d->setupMenu();
    QTimer* keyListTimer = new QTimer( this );
    connect( keyListTimer, SIGNAL( timeout() ), SLOT( listKeys() ) );
    keyListTimer->setInterval( 5 * 60 * 1000 );
    keyListTimer->start();
    QTimer::singleShot( 0, this, SLOT( listKeys() ) );
}

MainWindow::~MainWindow() {
    delete d;
}

void MainWindow::Private::listKeys() {
    startKeyListing( "openpgp" );
    startKeyListing( "smime" );
}

TrayIconListener::TrayIconListener( QWidget* mainWindow, QObject* parent ) : QObject( parent ), m_mainWindow( mainWindow )
{
    assert( m_mainWindow );
}

void TrayIconListener::activated( QSystemTrayIcon::ActivationReason reason )
{
    if ( reason != QSystemTrayIcon::Trigger )
        return;
    const bool visible = !m_mainWindow->isVisible();
    if ( visible ) {
        if ( m_prevGeometry.isValid() )
            m_mainWindow->setGeometry( m_prevGeometry );
        m_mainWindow->setVisible( true );
    } else {
        m_prevGeometry = m_mainWindow->geometry();
        m_mainWindow->setVisible( false );
    }
}

StatusBarUpdater::StatusBarUpdater( QStatusBar* bar, QObject* parent ) : QObject( parent ), m_bar( bar ), m_pendingJobs( 0 ) {
    assert( m_bar );
}

void StatusBarUpdater::registerJob( Kleo::KeyListJob* job ) {
    //TODO: handle errors
    connect( job, SIGNAL( result( GpgME::KeyListResult ) ),
             SLOT( keyListResult( GpgME::KeyListResult ) ) );
    ++m_pendingJobs;
    m_bar->showMessage( i18n("Fetching keys...") );
}

void StatusBarUpdater::keyListResult( const GpgME::KeyListResult& result ) {
    Q_UNUSED( result );
    --m_pendingJobs;
    assert( m_pendingJobs >= 0 );
    if ( m_pendingJobs == 0 )
        m_bar->clearMessage();
}

#include "mainwindow_p.moc"
#include "mainwindow.moc"
<|endoftext|>