<commit_before>
#include "components/graph_panel.h"

#include <math.h>

#include "ui.h"
#include "libs/types.h"
#include "libs/imgui/imgui.h"
#include "libs/mathlib.h"
#include "libpapaya.h"

const Vec2 node_sz = Vec2(36, 36);
const float slot_radius = 4.0f;

GraphPanel* init_graph_panel()
{
    GraphPanel* g = (GraphPanel*) calloc(sizeof(*g), 1);
    g->scroll_pos = Vec2(0,0);
    g->node_properties_panel_height = 200.0f;
    g->width = 300.0f;
    g->cur_node = 0;
    g->dragged_slot = 0;
    g->displaced_slot = 0;
    return g;
}

void destroy_graph_panel(GraphPanel* g)
{
    free(g);
}

static Vec2 get_slot_pos(PapayaSlot* slot)
{
    return Vec2(slot->node->pos_x, slot->node->pos_y)
         + Vec2(node_sz.x * slot->pos_x,
                node_sz.y * slot->pos_y);
}

static Vec2 get_output_slot_pos(PapayaNode* node)
{
    return Vec2(node->pos_x, node->pos_y) + Vec2(node_sz.x * 0.5f, 0);
}

static Vec2 get_input_slot_pos(PapayaNode* node)
{
    return get_output_slot_pos(node) + Vec2(0, node_sz.y);
}

static PapayaSlot* find_snapped_slot(PapayaMemory* mem, Vec2 offset)
{
    GraphPanel* g = mem->graph_panel;
    Vec2 m = mem->mouse.pos;

    for (int i = 0; i < mem->doc->num_nodes; i++) {
        PapayaNode* n = &mem->doc->nodes[i];
        for (int j = 0; j < n->num_slots; j++) {
            PapayaSlot* s = &n->slots[j];
            Vec2 p = offset + get_slot_pos(s);
            if (m.x >= p.x &&
                m.y >= p.y &&
                m.x <= p.x + slot_radius &&
                m.y <= p.y + slot_radius) {
                return s;
           }
        }
    }

    return 0;
}

static Vec2 get_bezier_bend(PapayaSlot* s)
{
    switch (s->pos){
        case PapayaSlotPos_In:     return Vec2(0,+10);
        case PapayaSlotPos_Out:    return Vec2(0,-10);
        case PapayaSlotPos_InMask: return Vec2(+20,0);
    }
    return Vec2();
}

/*
    Draws a bezier curve between the two given slots. If a slot is null, then
    the mouse position is used instead of the slot position.
*/
static void draw_link(PapayaSlot* a, PapayaSlot* b, PapayaMemory* mem,
                      Vec2 offset, ImDrawList* draw_list)
{
    Vec2 v1 = a ? offset + get_slot_pos(a) : mem->mouse.pos; // Positions
    Vec2 v2 = b ? offset + get_slot_pos(b) : mem->mouse.pos; //
    Vec2 u1 = a ? get_bezier_bend(a) : Vec2(); // Bends
    Vec2 u2 = b ? get_bezier_bend(b) : Vec2(); //

    draw_list->AddBezierCurve(v1,
                              v1 + u1,
                              v2 + u2,
                              v2,
                              ImColor(220, 163,89, 150),
                              4.0f); // Link thickness
}

static void draw_nodes(PapayaMemory* mem)
{
    GraphPanel* g = mem->graph_panel;
    Vec2 offset = ImGui::GetCursorScreenPos() + g->scroll_pos;
    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    int hovered_node = -1;

    for (int i = 0; i < mem->doc->num_nodes; i++) {
        PapayaNode* n = &mem->doc->nodes[i];
        Vec2 pos = offset + Vec2(n->pos_x - 1, n->pos_y - 1);

        ImGui::PushID(i);

        // Slots
        for (int j = 0; j < n->num_slots; j++) {
            PapayaSlot* s = &n->slots[j];
            Vec2 pos = offset + Vec2(n->pos_x, n->pos_y)
                              + Vec2(node_sz.x * s->pos_x,
                                     node_sz.y * s->pos_y);
            Vec2 dia = Vec2(2.0f * slot_radius, 2.0f * slot_radius);
            ImGui::PushID(j);
            ImGui::SetCursorScreenPos(pos - (dia * 0.5f));
            ImGui::InvisibleButton("slot", dia);
            draw_list->AddCircleFilled(pos, slot_radius,
                                       (ImGui::IsItemHovered() ?
                                        ImColor(255,150,150,255) :
                                        ImColor(150,150,150,150)));

            if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
                if (!s->to[0] || s->is_out) {
                    g->dragged_slot = s;
                } else {
                    g->displaced_slot = s;
                    g->dragged_slot = s->to[0];
                }
            }
            ImGui::PopID();
        }

        draw_list->ChannelsSetCurrent(0);
        ImGui::SetCursorScreenPos(pos);
        ImGui::InvisibleButton("node", node_sz);
        if (ImGui::IsItemHovered()) {
            hovered_node = i;
        }

        if (ImGui::IsItemActive()) {
            if (g->cur_node != i) {
                g->cur_node = i;
                core::update_canvas(mem);
            }
            if (ImGui::IsMouseDragging(0)) {
                n->pos_x += ImGui::GetIO().MouseDelta.x;
                n->pos_y += ImGui::GetIO().MouseDelta.y;
            }
        }

#if 0
        // Node debug info
        {
            ImGui::SetCursorScreenPos(pos + Vec2(node_sz.x + 5,0));
            int in = -1;
            int out = -1;
            if (n->in) {
                in = n->in - mem->doc->nodes;
            }
            if (n->out) {
                out = n->out - mem->doc->nodes;
            }
            // ImGui::Text("in: %d\nout: %d", in, out);
            ImGui::Text("%s", n->name);
        }
#endif

        // Thumbnail
        draw_list->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(pos);
        ImGui::BeginGroup(); // Lock horizontal position
        {
            ImColor c = (hovered_node == i ||
                         g->cur_node == i) ?
                ImColor(220,163,89, 150) : ImColor(60,60,60);
            // TODO: Optimization: Use mipmaps here.
            // TODO: Unstretch aspect ratio
            ImGui::Image(0, node_sz, Vec2(0,0), Vec2(1,1),
                         ImVec4(1,1,1,1), c);
        }
        ImGui::EndGroup();

        // Incoming links
        draw_list->ChannelsSetCurrent(0);

        for (int j = 0; j < n->num_slots; j++) {

            PapayaSlot* t = &n->slots[j];
            if (t->is_out) {
                continue;
            }

            PapayaSlot* b = t->to[0];
            if (!b) {
                continue;
            }

            if (g->dragged_slot &&
                !g->dragged_slot->is_out &&
                g->dragged_slot->node == n) {
                // This link is being dragged. Skip the normal drawing and
                // handle this in the link interaction code
                continue;
            }

            if (g->displaced_slot &&
                g->displaced_slot->node == n) {
                // continue;
            }

            draw_link(b, t, mem, offset, draw_list);
        }

        ImGui::PopID();
    }

    // Link interaction
    if (g->dragged_slot) {

        PapayaNode* d = g->dragged_slot->node;
        PapayaSlot* s = find_snapped_slot(mem, offset);

        draw_link(s, g->dragged_slot, mem, offset, draw_list);

        if (ImGui::IsMouseReleased(0)) {

            if (s) {
                if (g->displaced_slot) {
                    papaya_disconnect(g->displaced_slot, g->dragged_slot);
                }
                papaya_connect(g->dragged_slot, s);

            } else if (g->displaced_slot) {
                // Disconnection
                papaya_disconnect(g->displaced_slot, g->displaced_slot->to[0]);
            }

            g->dragged_slot = 0;
            g->displaced_slot = 0;

            core::update_canvas(mem);
        }

    }
}

void draw_graph_panel(PapayaMemory* mem)
{
    GraphPanel* g = mem->graph_panel;

    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, Vec2(5, 5));
    ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, Vec2(5, 2));
    ImGui::PushStyleColor(ImGuiCol_WindowBg, mem->colors[PapayaCol_Clear]);

    float x = mem->window.width - 36 - g->width; // Panel X
    float y = 55; // Panel Y
    float w = g->width; // Panel width
    float h = g->node_properties_panel_height; // Panel height

    // -------------------------------------------------------------------------
#if 1
    ImGui::SetNextWindowPos(Vec2(x, y));
    ImGui::SetNextWindowSize(Vec2(w, h));

    ImGui::Begin("Node properties", 0, mem->window.default_imgui_flags);

    ImGui::Checkbox(mem->doc->nodes[g->cur_node].name,
                    (bool*)&mem->doc->nodes[g->cur_node].is_active);
    ImGui::Text("Node properties controls go here");

    ImGui::End();
#endif
    // -------------------------------------------------------------------------

    y += h;
    h = mem->window.height - 58.0f - h;
    ImGui::SetNextWindowPos(Vec2(x, y));
    ImGui::SetNextWindowSize(Vec2(w, h));

    ImGui::Begin("Nodes", 0, mem->window.default_imgui_flags);

    ImGui::BeginGroup();

    const Vec2 NODE_WINDOW_PADDING(2.0f, 2.0f);

    // Create our child canvas
    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, Vec2(1,1));
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, Vec2(0,0));
    ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(60,60,70,200));
    ImGui::BeginChild("scrolling_region", Vec2(0,0), true, ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoMove);
    ImGui::PushItemWidth(120.0f);

    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    draw_list->ChannelsSplit(2);

    // Draw the grid
    {
        ImU32 col = ImColor(200,200,200,40);
        float grid_sz = 50.0f;
        Vec2 win_pos = ImGui::GetCursorScreenPos();
        Vec2 win_sz = ImGui::GetWindowSize();

        // Vertical lines
        float x = fmodf(g->scroll_pos.x, grid_sz);
        while (x < win_sz.x) {
            draw_list->AddLine(win_pos + Vec2(x, 0),
                               win_pos + Vec2(x, win_sz.y), col);
            x += grid_sz;
        }

        // Horizontal lines
        float y = fmodf(g->scroll_pos.y, grid_sz);
        while (y < win_sz.y) {
            draw_list->AddLine(win_pos + Vec2(0, y),
                               win_pos + Vec2(win_sz.x, y), col);
            y += grid_sz;
        };
    }

    // Display nodes
    draw_nodes(mem);
    draw_list->ChannelsMerge();

    // Scrolling
    if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(2, 0.0f))
        g->scroll_pos += ImGui::GetIO().MouseDelta;

    ImGui::PopItemWidth();
    ImGui::EndChild();
    ImGui::PopStyleColor();
    ImGui::PopStyleVar(2);
    ImGui::EndGroup();

    ImGui::End();
    ImGui::PopStyleVar(2);
    ImGui::PopStyleColor();
}
<commit_msg>Improved snapping<commit_after>
#include "components/graph_panel.h"

#include <math.h>

#include "ui.h"
#include "libs/types.h"
#include "libs/imgui/imgui.h"
#include "libs/mathlib.h"
#include "libpapaya.h"

const Vec2 node_sz = Vec2(36, 36);
const float slot_radius = 4.0f;

GraphPanel* init_graph_panel()
{
    GraphPanel* g = (GraphPanel*) calloc(sizeof(*g), 1);
    g->scroll_pos = Vec2(0,0);
    g->node_properties_panel_height = 200.0f;
    g->width = 300.0f;
    g->cur_node = 0;
    g->dragged_slot = 0;
    g->displaced_slot = 0;
    return g;
}

void destroy_graph_panel(GraphPanel* g)
{
    free(g);
}

static Vec2 get_slot_pos(PapayaSlot* slot)
{
    return Vec2(slot->node->pos_x, slot->node->pos_y)
         + Vec2(node_sz.x * slot->pos_x,
                node_sz.y * slot->pos_y);
}

static Vec2 get_output_slot_pos(PapayaNode* node)
{
    return Vec2(node->pos_x, node->pos_y) + Vec2(node_sz.x * 0.5f, 0);
}

static Vec2 get_input_slot_pos(PapayaNode* node)
{
    return get_output_slot_pos(node) + Vec2(0, node_sz.y);
}

static PapayaSlot* find_snapped_slot(PapayaMemory* mem, Vec2 offset)
{
    GraphPanel* g = mem->graph_panel;
    Vec2 m = mem->mouse.pos;
    PapayaNode* snapped_node = 0; // Snapped node

    // Find the node that is currently being moused over
    for (int i = 0; i < mem->doc->num_nodes; i++) {
        PapayaNode* n = &mem->doc->nodes[i];

        Vec2 p = offset + Vec2(n->pos_x, n->pos_y);
        if (m.x >= p.x &&
            m.y >= p.y &&
            m.x <= p.x + node_sz.x &&
            m.y <= p.y + node_sz.y) {
            snapped_node = n;
            break;
        }
    }

    if (snapped_node) {
        PapayaSlot* min_slot = 0;
        float min_dist = FLT_MAX;

        // Find the closest slot to the mouse in the snapped node
        for (int j = 0; j < snapped_node->num_slots; j++) {
            PapayaSlot* s = &snapped_node->slots[j];
            float dist = math::distance(offset + get_slot_pos(s), m);
            // TODO: Snappability check goes here, to verify the absence of
            // cycles and the compatibility of slots
            if (min_dist > dist) {
                min_dist = dist;
                min_slot = s;
            }
        }

        if (min_slot) {
            // Compatible slot exists. Snap to it.
            return min_slot;
        }
    }

    return 0;
}

static Vec2 get_bezier_bend(PapayaSlot* s)
{
    switch (s->pos){
        case PapayaSlotPos_In:     return Vec2(0,+10);
        case PapayaSlotPos_Out:    return Vec2(0,-10);
        case PapayaSlotPos_InMask: return Vec2(+20,0);
    }
    return Vec2();
}

/*
    Draws a bezier curve between the two given slots. If a slot is null, then
    the mouse position is used instead of the slot position.
*/
static void draw_link(PapayaSlot* a, PapayaSlot* b, PapayaMemory* mem,
                      Vec2 offset, ImDrawList* draw_list)
{
    Vec2 v1 = a ? offset + get_slot_pos(a) : mem->mouse.pos; // Positions
    Vec2 v2 = b ? offset + get_slot_pos(b) : mem->mouse.pos; //
    Vec2 u1 = a ? get_bezier_bend(a) : Vec2(); // Bends
    Vec2 u2 = b ? get_bezier_bend(b) : Vec2(); //

    draw_list->AddBezierCurve(v1,
                              v1 + u1,
                              v2 + u2,
                              v2,
                              ImColor(220, 163,89, 150),
                              4.0f); // Link thickness
}

static void draw_nodes(PapayaMemory* mem)
{
    GraphPanel* g = mem->graph_panel;
    Vec2 offset = ImGui::GetCursorScreenPos() + g->scroll_pos;
    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    int hovered_node = -1;

    for (int i = 0; i < mem->doc->num_nodes; i++) {
        PapayaNode* n = &mem->doc->nodes[i];
        Vec2 pos = offset + Vec2(n->pos_x - 1, n->pos_y - 1);

        ImGui::PushID(i);

        // Slots
        for (int j = 0; j < n->num_slots; j++) {
            PapayaSlot* s = &n->slots[j];
            Vec2 pos = offset + Vec2(n->pos_x, n->pos_y)
                              + Vec2(node_sz.x * s->pos_x,
                                     node_sz.y * s->pos_y);
            Vec2 dia = Vec2(2.0f * slot_radius, 2.0f * slot_radius);
            ImGui::PushID(j);
            ImGui::SetCursorScreenPos(pos - (dia * 0.5f));
            ImGui::InvisibleButton("slot", dia);
            draw_list->AddCircleFilled(pos, slot_radius,
                                       (ImGui::IsItemHovered() ?
                                        ImColor(255,150,150,255) :
                                        ImColor(150,150,150,150)));

            if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
                if (!s->to[0] || s->is_out) {
                    g->dragged_slot = s;
                } else {
                    g->displaced_slot = s;
                    g->dragged_slot = s->to[0];
                }
            }
            ImGui::PopID();
        }

        draw_list->ChannelsSetCurrent(0);
        ImGui::SetCursorScreenPos(pos);
        ImGui::InvisibleButton("node", node_sz);
        if (ImGui::IsItemHovered()) {
            hovered_node = i;
        }

        if (ImGui::IsItemActive()) {
            if (g->cur_node != i) {
                g->cur_node = i;
                core::update_canvas(mem);
            }
            if (ImGui::IsMouseDragging(0)) {
                n->pos_x += ImGui::GetIO().MouseDelta.x;
                n->pos_y += ImGui::GetIO().MouseDelta.y;
            }
        }

#if 0
        // Node debug info
        {
            ImGui::SetCursorScreenPos(pos + Vec2(node_sz.x + 5,0));
            int in = -1;
            int out = -1;
            if (n->in) {
                in = n->in - mem->doc->nodes;
            }
            if (n->out) {
                out = n->out - mem->doc->nodes;
            }
            // ImGui::Text("in: %d\nout: %d", in, out);
            ImGui::Text("%s", n->name);
        }
#endif

        // Thumbnail
        draw_list->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(pos);
        ImGui::BeginGroup(); // Lock horizontal position
        {
            ImColor c = (hovered_node == i ||
                         g->cur_node == i) ?
                ImColor(220,163,89, 150) : ImColor(60,60,60);
            // TODO: Optimization: Use mipmaps here.
            // TODO: Unstretch aspect ratio
            ImGui::Image(0, node_sz, Vec2(0,0), Vec2(1,1),
                         ImVec4(1,1,1,1), c);
        }
        ImGui::EndGroup();

        // Incoming links
        draw_list->ChannelsSetCurrent(0);

        for (int j = 0; j < n->num_slots; j++) {

            PapayaSlot* t = &n->slots[j];
            if (t->is_out) {
                continue;
            }

            PapayaSlot* b = t->to[0];
            if (!b) {
                continue;
            }

            if (g->dragged_slot &&
                !g->dragged_slot->is_out &&
                g->dragged_slot->node == n) {
                // This link is being dragged. Skip the normal drawing and
                // handle this in the link interaction code
                continue;
            }

            if (g->displaced_slot &&
                g->displaced_slot->node == n) {
                // continue;
            }

            draw_link(b, t, mem, offset, draw_list);
        }

        ImGui::PopID();
    }

    // Link interaction
    if (g->dragged_slot) {

        PapayaNode* d = g->dragged_slot->node;
        PapayaSlot* s = find_snapped_slot(mem, offset);

        draw_link(s, g->dragged_slot, mem, offset, draw_list);

        if (ImGui::IsMouseReleased(0)) {

            if (s) {
                if (g->displaced_slot) {
                    papaya_disconnect(g->displaced_slot, g->dragged_slot);
                }
                papaya_connect(g->dragged_slot, s);

            } else if (g->displaced_slot) {
                // Disconnection
                papaya_disconnect(g->displaced_slot, g->displaced_slot->to[0]);
            }

            g->dragged_slot = 0;
            g->displaced_slot = 0;

            core::update_canvas(mem);
        }

    }
}

void draw_graph_panel(PapayaMemory* mem)
{
    GraphPanel* g = mem->graph_panel;

    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, Vec2(5, 5));
    ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, Vec2(5, 2));
    ImGui::PushStyleColor(ImGuiCol_WindowBg, mem->colors[PapayaCol_Clear]);

    float x = mem->window.width - 36 - g->width; // Panel X
    float y = 55; // Panel Y
    float w = g->width; // Panel width
    float h = g->node_properties_panel_height; // Panel height

    // -------------------------------------------------------------------------
#if 1
    ImGui::SetNextWindowPos(Vec2(x, y));
    ImGui::SetNextWindowSize(Vec2(w, h));

    ImGui::Begin("Node properties", 0, mem->window.default_imgui_flags);

    ImGui::Checkbox(mem->doc->nodes[g->cur_node].name,
                    (bool*)&mem->doc->nodes[g->cur_node].is_active);
    ImGui::Text("Node properties controls go here");

    ImGui::End();
#endif
    // -------------------------------------------------------------------------

    y += h;
    h = mem->window.height - 58.0f - h;
    ImGui::SetNextWindowPos(Vec2(x, y));
    ImGui::SetNextWindowSize(Vec2(w, h));

    ImGui::Begin("Nodes", 0, mem->window.default_imgui_flags);

    ImGui::BeginGroup();

    const Vec2 NODE_WINDOW_PADDING(2.0f, 2.0f);

    // Create our child canvas
    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, Vec2(1,1));
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, Vec2(0,0));
    ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(60,60,70,200));
    ImGui::BeginChild("scrolling_region", Vec2(0,0), true, ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoMove);
    ImGui::PushItemWidth(120.0f);

    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    draw_list->ChannelsSplit(2);

    // Draw the grid
    {
        ImU32 col = ImColor(200,200,200,40);
        float grid_sz = 50.0f;
        Vec2 win_pos = ImGui::GetCursorScreenPos();
        Vec2 win_sz = ImGui::GetWindowSize();

        // Vertical lines
        float x = fmodf(g->scroll_pos.x, grid_sz);
        while (x < win_sz.x) {
            draw_list->AddLine(win_pos + Vec2(x, 0),
                               win_pos + Vec2(x, win_sz.y), col);
            x += grid_sz;
        }

        // Horizontal lines
        float y = fmodf(g->scroll_pos.y, grid_sz);
        while (y < win_sz.y) {
            draw_list->AddLine(win_pos + Vec2(0, y),
                               win_pos + Vec2(win_sz.x, y), col);
            y += grid_sz;
        };
    }

    // Display nodes
    draw_nodes(mem);
    draw_list->ChannelsMerge();

    // Scrolling
    if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(2, 0.0f))
        g->scroll_pos += ImGui::GetIO().MouseDelta;

    ImGui::PopItemWidth();
    ImGui::EndChild();
    ImGui::PopStyleColor();
    ImGui::PopStyleVar(2);
    ImGui::EndGroup();

    ImGui::End();
    ImGui::PopStyleVar(2);
    ImGui::PopStyleColor();
}
<|endoftext|>


<commit_before>#include "ui/QBouton.h"
#include <QPainter>
#include <QPaintEvent>
#include <QtMath>

QBouton::QBouton(QVariant id, bool resizeInsteadOfCropping, bool smartSizeHint, int border, QColor color, QWidget *parent)
	: QPushButton(parent), m_id(std::move(id)), m_resizeInsteadOfCropping(resizeInsteadOfCropping), m_smartSizeHint(smartSizeHint), m_penColor(std::move(color)), m_border(border), m_center(true), m_progress(0), m_progressMax(0), m_invertToggle(false), m_counter(QString())
{}

void QBouton::scale(const QPixmap &image, QSize bounds)
{
	const QSize size = image.size().scaled(bounds, Qt::KeepAspectRatio);
	if (size != image.size()) {
		setIcon(image.scaled(bounds, Qt::KeepAspectRatio, Qt::SmoothTransformation));
	} else {
		setIcon(image);
	}
	setIconSize(size);
	resize(size);
}

QVariant QBouton::id() const
{ return m_id; }
void QBouton::setId(const QVariant &id)
{ m_id = id; }

void QBouton::setProgress(qint64 current, qint64 max)
{
	m_progress = current;
	m_progressMax = max;

	repaint();
}

void QBouton::setInvertToggle(bool invertToggle)
{ m_invertToggle = invertToggle; }
void QBouton::setCounter(const QString &counter)
{ m_counter = counter; }

void QBouton::paintEvent(QPaintEvent *event)
{
	// Used for normal buttons
	if (!m_resizeInsteadOfCropping && m_border == 0 && m_progressMax == 0 && m_counter.isEmpty()) {
		QPushButton::paintEvent(event);
		return;
	}

	QPainter painter(this);
	const QRect region = m_smartSizeHint ? contentsRect() : event->rect();
	const QSize iconSize = getIconSize(region.width(), region.height());
	const int p = m_border;
	int x = region.x();
	int y = region.y();
	int w = iconSize.width() + 2 * p;
	int h = iconSize.height() + 2 * p;

	// Ignore invalid images
	if (w == 0 || h == 0) {
		return;
	}

	// Center the image
	if (m_center) {
		x += (region.width() - w) / 2;
		y += (region.height() - h) / 2;
	}

	// Draw image
	const QIcon::Mode mode = this->isChecked() ? QIcon::Selected : QIcon::Normal;
	if (w > h) {
		icon().paint(&painter, x + p, y + p, w - 2 * p, w - 2 * p, Qt::AlignLeft | Qt::AlignTop, mode);
	} else {
		icon().paint(&painter, x + p, y + p, h - 2 * p, h - 2 * p, Qt::AlignLeft | Qt::AlignTop, mode);
	}

	// Clip borders overflows
	painter.setClipRect(x, y, w, h);

	// Draw borders
	if (p > 0 && m_penColor.isValid()) {
		QPen pen(m_penColor);
		pen.setWidth(p * 2);
		painter.setPen(pen);
		painter.drawRect(qMax(x, 0), qMax(y, 0), qMin(w, size().width()), qMin(h, size().height()));
	}

	// Draw progress
	if (m_progressMax > 0 && m_progress > 0 && m_progress < m_progressMax) {
		const int lineHeight = 6;
		const int a = p + lineHeight / 2;

		const qreal ratio = static_cast<qreal>(m_progress) / m_progressMax;
		QPoint p1(qMax(x, 0) + a, qMax(y, 0) + a);
		QPoint p2(qFloor(p1.x() + (iconSize.width() - a) * ratio), p1.y());

		if (p2.x() > p1.x()) {
			QPen pen(QColor(0, 200, 0));
			pen.setWidth(lineHeight);
			painter.setPen(pen);
			painter.drawLine(p1, p2);
		}
	}

	// Draw counter
	if (!m_counter.isEmpty()) {
		const int right = qMax(x, 0) + qMin(w, size().width());
		const int dim = 10 + 5 * m_counter.length();
		const double pad = 1.5;
		const QRectF notificationRect(right - dim - pad, qMax(y, 0) + pad, dim, 20);
		const int radius = qFloor(qMin(dim, 20) / 2.0);

		painter.setRenderHint(QPainter::Antialiasing);

		QPainterPath path;
		path.addRoundedRect(notificationRect, radius, radius);

		const QPen pen(Qt::black, 1);
		painter.setPen(pen);
		painter.fillPath(path, QColor(255, 0, 0));
		painter.drawPath(path);

		painter.setPen(QPen(Qt::white));
		painter.drawText(notificationRect, Qt::AlignCenter, m_counter);
	}
}

QSize QBouton::getIconSize(int regionWidth, int regionHeight, bool wOnly) const
{
	int w = iconSize().width();
	int h = iconSize().height();

	if (wOnly && w <= regionWidth) {
		return iconSize();
	}

	// Calculate ratio to resize by keeping proportions
	if (m_resizeInsteadOfCropping) {
		const qreal coefficient = wOnly
			? qMin(1.0, static_cast<qreal>(regionWidth) / static_cast<qreal>(w))
			: qMin(1.0, qMin(static_cast<qreal>(regionWidth) / static_cast<qreal>(w), static_cast<qreal>(regionHeight) / static_cast<qreal>(h)));
		w *= coefficient;
		h *= coefficient;
	}

	return { w, h };
}

void QBouton::resizeEvent(QResizeEvent *event)
{
	QPushButton::resizeEvent(event);

	if (m_smartSizeHint) {
		updateGeometry();
	}
}

QSize QBouton::sizeHint() const
{
	// Used for normal buttons
	if (!m_smartSizeHint || (!m_resizeInsteadOfCropping && m_border == 0)) {
		return QPushButton::sizeHint();
	}

	QSize current = size();
	return getIconSize(current.width(), current.height(), true);
}

void QBouton::mousePressEvent(QMouseEvent *event)
{
	// Ignore clicks outside the thumbnail
	const QSize imgSize = sizeHint();
	const QSize size = this->size();
	const int wMargin = (size.width() - imgSize.width()) / 2;
	const int hMargin = (size.height() - imgSize.height()) / 2;
	const QPoint pos = event->pos();
	if (pos.x() < wMargin
			|| pos.y() < hMargin
			|| pos.x() > imgSize.width() + wMargin
			|| pos.y() > imgSize.height() + hMargin) {
		event->ignore();
		return;
	}

	if (event->button() == Qt::LeftButton) {
		const bool ctrlPressed = event->modifiers().testFlag(Qt::ControlModifier);
		if (ctrlPressed != m_invertToggle) {
			this->toggle();
			const bool range = event->modifiers().testFlag(Qt::ShiftModifier);
			emit this->toggled(m_id, this->isChecked(), range);
			emit this->toggled(m_id.toString(), this->isChecked(), range);
			emit this->toggled(m_id.toInt(), this->isChecked(), range);
		} else {
			emit this->appui(m_id);
			emit this->appui(m_id.toString());
			emit this->appui(m_id.toInt());
		}
	} else if (event->button() == Qt::RightButton) {
		emit this->rightClick(m_id);
		emit this->rightClick(m_id.toString());
		emit this->rightClick(m_id.toInt());
	} else if (event->button() == Qt::MidButton) {
		emit this->middleClick(m_id);
		emit this->middleClick(m_id.toString());
		emit this->middleClick(m_id.toInt());
	} else {
		event->ignore();
		return;
	}

	event->accept();
}
<commit_msg>Add missing QPainterPath include in QBouton (PR #2004, fix #1993)<commit_after>#include "ui/QBouton.h"
#include <QPainter>
#include <QPainterPath>
#include <QPaintEvent>
#include <QtMath>

QBouton::QBouton(QVariant id, bool resizeInsteadOfCropping, bool smartSizeHint, int border, QColor color, QWidget *parent)
	: QPushButton(parent), m_id(std::move(id)), m_resizeInsteadOfCropping(resizeInsteadOfCropping), m_smartSizeHint(smartSizeHint), m_penColor(std::move(color)), m_border(border), m_center(true), m_progress(0), m_progressMax(0), m_invertToggle(false), m_counter(QString())
{}

void QBouton::scale(const QPixmap &image, QSize bounds)
{
	const QSize size = image.size().scaled(bounds, Qt::KeepAspectRatio);
	if (size != image.size()) {
		setIcon(image.scaled(bounds, Qt::KeepAspectRatio, Qt::SmoothTransformation));
	} else {
		setIcon(image);
	}
	setIconSize(size);
	resize(size);
}

QVariant QBouton::id() const
{ return m_id; }
void QBouton::setId(const QVariant &id)
{ m_id = id; }

void QBouton::setProgress(qint64 current, qint64 max)
{
	m_progress = current;
	m_progressMax = max;

	repaint();
}

void QBouton::setInvertToggle(bool invertToggle)
{ m_invertToggle = invertToggle; }
void QBouton::setCounter(const QString &counter)
{ m_counter = counter; }

void QBouton::paintEvent(QPaintEvent *event)
{
	// Used for normal buttons
	if (!m_resizeInsteadOfCropping && m_border == 0 && m_progressMax == 0 && m_counter.isEmpty()) {
		QPushButton::paintEvent(event);
		return;
	}

	QPainter painter(this);
	const QRect region = m_smartSizeHint ? contentsRect() : event->rect();
	const QSize iconSize = getIconSize(region.width(), region.height());
	const int p = m_border;
	int x = region.x();
	int y = region.y();
	int w = iconSize.width() + 2 * p;
	int h = iconSize.height() + 2 * p;

	// Ignore invalid images
	if (w == 0 || h == 0) {
		return;
	}

	// Center the image
	if (m_center) {
		x += (region.width() - w) / 2;
		y += (region.height() - h) / 2;
	}

	// Draw image
	const QIcon::Mode mode = this->isChecked() ? QIcon::Selected : QIcon::Normal;
	if (w > h) {
		icon().paint(&painter, x + p, y + p, w - 2 * p, w - 2 * p, Qt::AlignLeft | Qt::AlignTop, mode);
	} else {
		icon().paint(&painter, x + p, y + p, h - 2 * p, h - 2 * p, Qt::AlignLeft | Qt::AlignTop, mode);
	}

	// Clip borders overflows
	painter.setClipRect(x, y, w, h);

	// Draw borders
	if (p > 0 && m_penColor.isValid()) {
		QPen pen(m_penColor);
		pen.setWidth(p * 2);
		painter.setPen(pen);
		painter.drawRect(qMax(x, 0), qMax(y, 0), qMin(w, size().width()), qMin(h, size().height()));
	}

	// Draw progress
	if (m_progressMax > 0 && m_progress > 0 && m_progress < m_progressMax) {
		const int lineHeight = 6;
		const int a = p + lineHeight / 2;

		const qreal ratio = static_cast<qreal>(m_progress) / m_progressMax;
		QPoint p1(qMax(x, 0) + a, qMax(y, 0) + a);
		QPoint p2(qFloor(p1.x() + (iconSize.width() - a) * ratio), p1.y());

		if (p2.x() > p1.x()) {
			QPen pen(QColor(0, 200, 0));
			pen.setWidth(lineHeight);
			painter.setPen(pen);
			painter.drawLine(p1, p2);
		}
	}

	// Draw counter
	if (!m_counter.isEmpty()) {
		const int right = qMax(x, 0) + qMin(w, size().width());
		const int dim = 10 + 5 * m_counter.length();
		const double pad = 1.5;
		const QRectF notificationRect(right - dim - pad, qMax(y, 0) + pad, dim, 20);
		const int radius = qFloor(qMin(dim, 20) / 2.0);

		painter.setRenderHint(QPainter::Antialiasing);

		QPainterPath path;
		path.addRoundedRect(notificationRect, radius, radius);

		const QPen pen(Qt::black, 1);
		painter.setPen(pen);
		painter.fillPath(path, QColor(255, 0, 0));
		painter.drawPath(path);

		painter.setPen(QPen(Qt::white));
		painter.drawText(notificationRect, Qt::AlignCenter, m_counter);
	}
}

QSize QBouton::getIconSize(int regionWidth, int regionHeight, bool wOnly) const
{
	int w = iconSize().width();
	int h = iconSize().height();

	if (wOnly && w <= regionWidth) {
		return iconSize();
	}

	// Calculate ratio to resize by keeping proportions
	if (m_resizeInsteadOfCropping) {
		const qreal coefficient = wOnly
			? qMin(1.0, static_cast<qreal>(regionWidth) / static_cast<qreal>(w))
			: qMin(1.0, qMin(static_cast<qreal>(regionWidth) / static_cast<qreal>(w), static_cast<qreal>(regionHeight) / static_cast<qreal>(h)));
		w *= coefficient;
		h *= coefficient;
	}

	return { w, h };
}

void QBouton::resizeEvent(QResizeEvent *event)
{
	QPushButton::resizeEvent(event);

	if (m_smartSizeHint) {
		updateGeometry();
	}
}

QSize QBouton::sizeHint() const
{
	// Used for normal buttons
	if (!m_smartSizeHint || (!m_resizeInsteadOfCropping && m_border == 0)) {
		return QPushButton::sizeHint();
	}

	QSize current = size();
	return getIconSize(current.width(), current.height(), true);
}

void QBouton::mousePressEvent(QMouseEvent *event)
{
	// Ignore clicks outside the thumbnail
	const QSize imgSize = sizeHint();
	const QSize size = this->size();
	const int wMargin = (size.width() - imgSize.width()) / 2;
	const int hMargin = (size.height() - imgSize.height()) / 2;
	const QPoint pos = event->pos();
	if (pos.x() < wMargin
			|| pos.y() < hMargin
			|| pos.x() > imgSize.width() + wMargin
			|| pos.y() > imgSize.height() + hMargin) {
		event->ignore();
		return;
	}

	if (event->button() == Qt::LeftButton) {
		const bool ctrlPressed = event->modifiers().testFlag(Qt::ControlModifier);
		if (ctrlPressed != m_invertToggle) {
			this->toggle();
			const bool range = event->modifiers().testFlag(Qt::ShiftModifier);
			emit this->toggled(m_id, this->isChecked(), range);
			emit this->toggled(m_id.toString(), this->isChecked(), range);
			emit this->toggled(m_id.toInt(), this->isChecked(), range);
		} else {
			emit this->appui(m_id);
			emit this->appui(m_id.toString());
			emit this->appui(m_id.toInt());
		}
	} else if (event->button() == Qt::RightButton) {
		emit this->rightClick(m_id);
		emit this->rightClick(m_id.toString());
		emit this->rightClick(m_id.toInt());
	} else if (event->button() == Qt::MidButton) {
		emit this->middleClick(m_id);
		emit this->middleClick(m_id.toString());
		emit this->middleClick(m_id.toInt());
	} else {
		event->ignore();
		return;
	}

	event->accept();
}
<|endoftext|>


<commit_before>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5cpp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, 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 ofMERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Authors:
//   Eugen Wintersberger <eugen.wintersberger@desy.de>
//   Jan Kotanski <jan.kotanski@desy.de>
//
// Created on: Sep 12, 2017
//

#include <sstream>
#include <stdexcept>
#include <h5cpp/node/dataset.hpp>
#include <h5cpp/node/functions.hpp>
#include <h5cpp/filter/external_filter.hpp>
#include <h5cpp/error/error.hpp>

namespace hdf5 {
namespace node {

//=============================================================================
// implementation of private member functions
//=============================================================================

Node Dataset::create_dataset(const Group &base,
                             const Path &path,
                             const datatype::Datatype &type,
                             const dataspace::Dataspace &space,
                             const property::LinkCreationList &lcpl,
                             const property::DatasetCreationList &dcpl,
                             const property::DatasetAccessList &dapl)
{

  hid_t id = 0;

  if((id = H5Dcreate(static_cast<hid_t>(base),
                     static_cast<std::string>(path).c_str(),
                     static_cast<hid_t>(type),
                     static_cast<hid_t>(space),
                     static_cast<hid_t>(lcpl),
                     static_cast<hid_t>(dcpl),
                     static_cast<hid_t>(dapl))) < 0 )
  {
    std::stringstream ss;
    ss<<"Failure to create dataset ["<<path<<"] on group ["<<base.link().path()
      <<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
  H5Dclose(id);

  return Node(node::get_node(base,path));
}

//=============================================================================
// implementation of public member functions
//=============================================================================
Dataset::Dataset(const Node &node):
    Node(node)
{
  if(node.type()!=Type::DATASET)
  {
    std::stringstream ss;
    ss<<"Construction of a Dataset from a Node failed since ";
    ss<<"Node ["<<node.link().path()<<"] is not a dataset!";
    throw std::runtime_error(ss.str());
  }
}

Dataset::Dataset(const Group &base,const Path &path,
                 const datatype::Datatype &type,
                 const dataspace::Dataspace &space,
                 const property::LinkCreationList &lcpl,
                 const property::DatasetCreationList &dcpl,
                 const property::DatasetAccessList &dapl):
 Node(create_dataset(base,path,type,space,lcpl,dcpl,dapl))
{}

dataspace::Dataspace Dataset::dataspace() const
{
  hid_t id = H5Dget_space(static_cast<hid_t>(*this));
  if(id<0)
  {
    std::stringstream ss;
    ss<<"Failure retrieving dataspace for dataset "<<link().path()<<"!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
  return dataspace::Dataspace(ObjectHandle(id));
}

datatype::Datatype Dataset::datatype() const
{
  hid_t id = H5Dget_type(static_cast<hid_t>(*this));
  if(id<0)
  {
    std::stringstream ss;
    ss<<"Failure retrieving datatype for dataset "<<link().path()<<"!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }

  return datatype::Datatype(ObjectHandle(id));
}

property::DatasetCreationList Dataset::creation_list() const
{
  hid_t id = 0;
  if((id=H5Dget_create_plist(static_cast<hid_t>(*this)))<0)
  {
    std::stringstream ss;
    ss<<"Cannot obtain dataset creation property list for dataset ["
      <<link().path()<<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }

  return property::DatasetCreationList(ObjectHandle(id));
}

property::DatasetAccessList Dataset::access_list() const
{
  hid_t id=0;
  if((id=H5Dget_access_plist(static_cast<hid_t>(*this)))<0)
  {
    std::stringstream ss;
    ss<<"Failure obtaining dataset creation property list for dataset ["
      <<link().path()<<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }

  return property::DatasetAccessList(ObjectHandle(id));
}

void Dataset::extent(const Dimensions &dims) const
{
  resize(dims);
}

void Dataset::resize(const Dimensions &dims) const
{
  if(H5Dset_extent(static_cast<hid_t>(*this),dims.data())<0)
  {
    std::stringstream ss;
    ss<<"Failed to set extent for dataset "<<link().path()<<"!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
}

void Dataset::extent(size_t dim,ssize_t delta_elements) const
{
  resize_by(*this,dim,delta_elements);
}

#if H5_VERSION_GE(1,10,0)
void Dataset::refresh() const
{
  if(H5Drefresh(static_cast<hid_t>(*this))<0)
  {
    std::stringstream ss;
    ss<<"Failure to refresh dataset ["<<link().path()<<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
}

#endif

#if H5_VERSION_GE(1,10,2)

long long unsigned int Dataset::chunk_storage_size(
			 std::vector<long long unsigned int> offset) const
{
  long long unsigned int storage_size;
  if(H5Dget_chunk_storage_size(static_cast<hid_t>(*this),
			       offset.data(),
			       &storage_size)<0)
    {
      std::stringstream ss;
      ss<<"Failure to read chunk data size from dataset ["<<link().path()<<"]!";
      error::Singleton::instance().throw_with_stack(ss.str());
    }
  return storage_size;
}

#endif

void Dataset::write(const char *data,const property::DatasetTransferList &dtpl) const
{
  write(std::string(data),dtpl);
}

filter::ExternalFilters Dataset::filters() const
{
  filter::ExternalFilters efilters = filter::ExternalFilters();
  efilters.fill(creation_list());
  return efilters;
}

void resize_by(const Dataset &dataset,size_t dimension_index,ssize_t delta)
{
  dataspace::Dataspace space = dataset.dataspace();
  if(space.type()!=dataspace::Type::SIMPLE)
  {
    std::stringstream ss;
    ss<<"Dataset ["<<dataset.link().path()<<"] does not use a simple dataspace"
      <<" and thus cannot be extended!";
    throw std::runtime_error(ss.str());
  }
  dataspace::Simple simple_space(space);

  Dimensions current_dims = simple_space.current_dimensions();
  //check current dimensions
  if(dimension_index>=current_dims.size())
  {
    std::stringstream ss;
    ss<<"Dataset ["<<dataset.link().path()<<"] has rank "<<current_dims.size()
      <<" however you requested to change dimension "<<dimension_index
      <<" this would not work!";
    throw std::runtime_error(ss.str());
  }

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
  if((delta<0) && (current_dims[dimension_index] < static_cast<hsize_t>(abs(delta))))
  {
    std::stringstream ss;
    ss<<"Extent of dataset ["<<dataset.link().path()<<"] cannot be changed "
      <<" by "<<delta<<" along dimensions "<<dimension_index
      <<" (currently "<<current_dims[dimension_index]<<") as the resulting size"
      <<" would be negative";
    throw std::runtime_error(ss.str());
  }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

  current_dims[dimension_index] += delta;
  dataset.resize(current_dims);
}

} // namespace node
} // namespace hdf5
<commit_msg>Fix potential value truncation<commit_after>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5cpp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, 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 ofMERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Authors:
//   Eugen Wintersberger <eugen.wintersberger@desy.de>
//   Jan Kotanski <jan.kotanski@desy.de>
//
// Created on: Sep 12, 2017
//

#include <cstdlib>
#include <sstream>
#include <stdexcept>
#include <h5cpp/node/dataset.hpp>
#include <h5cpp/node/functions.hpp>
#include <h5cpp/filter/external_filter.hpp>
#include <h5cpp/error/error.hpp>

namespace hdf5 {
namespace node {

//=============================================================================
// implementation of private member functions
//=============================================================================

Node Dataset::create_dataset(const Group &base,
                             const Path &path,
                             const datatype::Datatype &type,
                             const dataspace::Dataspace &space,
                             const property::LinkCreationList &lcpl,
                             const property::DatasetCreationList &dcpl,
                             const property::DatasetAccessList &dapl)
{

  hid_t id = 0;

  if((id = H5Dcreate(static_cast<hid_t>(base),
                     static_cast<std::string>(path).c_str(),
                     static_cast<hid_t>(type),
                     static_cast<hid_t>(space),
                     static_cast<hid_t>(lcpl),
                     static_cast<hid_t>(dcpl),
                     static_cast<hid_t>(dapl))) < 0 )
  {
    std::stringstream ss;
    ss<<"Failure to create dataset ["<<path<<"] on group ["<<base.link().path()
      <<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
  H5Dclose(id);

  return Node(node::get_node(base,path));
}

//=============================================================================
// implementation of public member functions
//=============================================================================
Dataset::Dataset(const Node &node):
    Node(node)
{
  if(node.type()!=Type::DATASET)
  {
    std::stringstream ss;
    ss<<"Construction of a Dataset from a Node failed since ";
    ss<<"Node ["<<node.link().path()<<"] is not a dataset!";
    throw std::runtime_error(ss.str());
  }
}

Dataset::Dataset(const Group &base,const Path &path,
                 const datatype::Datatype &type,
                 const dataspace::Dataspace &space,
                 const property::LinkCreationList &lcpl,
                 const property::DatasetCreationList &dcpl,
                 const property::DatasetAccessList &dapl):
 Node(create_dataset(base,path,type,space,lcpl,dcpl,dapl))
{}

dataspace::Dataspace Dataset::dataspace() const
{
  hid_t id = H5Dget_space(static_cast<hid_t>(*this));
  if(id<0)
  {
    std::stringstream ss;
    ss<<"Failure retrieving dataspace for dataset "<<link().path()<<"!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
  return dataspace::Dataspace(ObjectHandle(id));
}

datatype::Datatype Dataset::datatype() const
{
  hid_t id = H5Dget_type(static_cast<hid_t>(*this));
  if(id<0)
  {
    std::stringstream ss;
    ss<<"Failure retrieving datatype for dataset "<<link().path()<<"!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }

  return datatype::Datatype(ObjectHandle(id));
}

property::DatasetCreationList Dataset::creation_list() const
{
  hid_t id = 0;
  if((id=H5Dget_create_plist(static_cast<hid_t>(*this)))<0)
  {
    std::stringstream ss;
    ss<<"Cannot obtain dataset creation property list for dataset ["
      <<link().path()<<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }

  return property::DatasetCreationList(ObjectHandle(id));
}

property::DatasetAccessList Dataset::access_list() const
{
  hid_t id=0;
  if((id=H5Dget_access_plist(static_cast<hid_t>(*this)))<0)
  {
    std::stringstream ss;
    ss<<"Failure obtaining dataset creation property list for dataset ["
      <<link().path()<<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }

  return property::DatasetAccessList(ObjectHandle(id));
}

void Dataset::extent(const Dimensions &dims) const
{
  resize(dims);
}

void Dataset::resize(const Dimensions &dims) const
{
  if(H5Dset_extent(static_cast<hid_t>(*this),dims.data())<0)
  {
    std::stringstream ss;
    ss<<"Failed to set extent for dataset "<<link().path()<<"!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
}

void Dataset::extent(size_t dim,ssize_t delta_elements) const
{
  resize_by(*this,dim,delta_elements);
}

#if H5_VERSION_GE(1,10,0)
void Dataset::refresh() const
{
  if(H5Drefresh(static_cast<hid_t>(*this))<0)
  {
    std::stringstream ss;
    ss<<"Failure to refresh dataset ["<<link().path()<<"]!";
    hdf5::error::Singleton::instance().throw_with_stack(ss.str());
  }
}

#endif

#if H5_VERSION_GE(1,10,2)

long long unsigned int Dataset::chunk_storage_size(
			 std::vector<long long unsigned int> offset) const
{
  long long unsigned int storage_size;
  if(H5Dget_chunk_storage_size(static_cast<hid_t>(*this),
			       offset.data(),
			       &storage_size)<0)
    {
      std::stringstream ss;
      ss<<"Failure to read chunk data size from dataset ["<<link().path()<<"]!";
      error::Singleton::instance().throw_with_stack(ss.str());
    }
  return storage_size;
}

#endif

void Dataset::write(const char *data,const property::DatasetTransferList &dtpl) const
{
  write(std::string(data),dtpl);
}

filter::ExternalFilters Dataset::filters() const
{
  filter::ExternalFilters efilters = filter::ExternalFilters();
  efilters.fill(creation_list());
  return efilters;
}

void resize_by(const Dataset &dataset,size_t dimension_index,ssize_t delta)
{
  dataspace::Dataspace space = dataset.dataspace();
  if(space.type()!=dataspace::Type::SIMPLE)
  {
    std::stringstream ss;
    ss<<"Dataset ["<<dataset.link().path()<<"] does not use a simple dataspace"
      <<" and thus cannot be extended!";
    throw std::runtime_error(ss.str());
  }
  dataspace::Simple simple_space(space);

  Dimensions current_dims = simple_space.current_dimensions();
  //check current dimensions
  if(dimension_index>=current_dims.size())
  {
    std::stringstream ss;
    ss<<"Dataset ["<<dataset.link().path()<<"] has rank "<<current_dims.size()
      <<" however you requested to change dimension "<<dimension_index
      <<" this would not work!";
    throw std::runtime_error(ss.str());
  }

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
  if((delta<0) && (current_dims[dimension_index] < static_cast<hsize_t>(std::abs(delta))))
  {
    std::stringstream ss;
    ss<<"Extent of dataset ["<<dataset.link().path()<<"] cannot be changed "
      <<" by "<<delta<<" along dimensions "<<dimension_index
      <<" (currently "<<current_dims[dimension_index]<<") as the resulting size"
      <<" would be negative";
    throw std::runtime_error(ss.str());
  }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

  current_dims[dimension_index] += delta;
  dataset.resize(current_dims);
}

} // namespace node
} // namespace hdf5
<|endoftext|>


<commit_before>#ifndef IMPL_AX_VECTOR_HPP
#define IMPL_AX_VECTOR_HPP

#include <cstddef>
#include <algorithm>
#include <vector>
#include <memory>

#include "prelude.hpp"

namespace ax
{
    // A vector with small size optimization.
    template<typename T, typename A = std::allocator<T>, std::size_t N = 4>
    class vector
    {
    public:

        CONSTRAINT(vector);
        using value_type = T;
        using size_type = std::size_t;
        using iterator = T*;
        using const_iterator = const T*;
        using allocator = A; // TODO: see if this is a meaningful trait name
        template<typename T2, typename A2, std::size_t N2>
        using reify = ax::vector<T2, A2, N2>;

        vector() : vector({ }) { }

        vector(std::initializer_list<T> il) :
            vector(il.begin(), il.end()) { }

        vector(const T* begin, const T* end)
        {
            VAR size = static_cast<std::size_t>(end - begin);
            if (size > N)
            {
                small_end = small_begin - 1;
                big_vector.insert(big_vector.begin(), begin, end);
            }
            else
            {
                small_end = small_begin;
                for (VAR i = 0_z; i < N && begin != end; ++i)
                {
                    *small_end = *begin;
                    ++small_end;
                    ++begin;
                }
            }
        }

        vector(const ax::vector<T, A, N>& that)
        {
            if (that.small_end < that.small_begin)
            {
                small_end = small_begin - 1;
                big_vector = that.big_vector;
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        vector(ax::vector<T, A, N>&& that)
        {
            if (that.small_end < that.small_begin)
            {
                small_end = small_begin - 1;
                big_vector = std::move(that.big_vector);
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        ~vector() = default;

        ax::vector<T, A, N>& operator=(const ax::vector<T, A, N>& that)
        {
            big_vector = that.big_vector;
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        ax::vector<T, A, N>& operator=(ax::vector<T, A, N>&& that)
        {
            big_vector = std::move(that.big_vector);
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        bool operator==(const ax::vector<T, A, N>& that) const
        {
            VAL size = this->size();
            if (size > N) return big_vector == that.big_vector;
            VAR result = true;
            for (VAR i = 0_z; result && i < size; ++i)
                result = small_begin[i] == that.small_begin[i];
            return result;
        }

        bool operator!=(const ax::vector<T, A, N>& that) const
        {
            return !(*this == that);
        }

        T* begin() { return big() ? big_vector.data() : small_begin; }
        T* end() { return big() ? big_vector.data() + big_vector.size() : small_end; }
        const T* cbegin() const { return const_cast<ax::vector<T, A, N>*>(this)->begin(); }
        const T* cend() const { return const_cast<ax::vector<T, A, N>*>(this)->end(); }
        const T* begin() const { return cbegin(); }
        const T* end() const { return cend(); }

        void push_back(const T& item)
        {
            if (big())
            {
                big_vector.push_back(item);
            }
            else if (size() == N)
            {
                big_vector.insert(big_vector.begin(), small_begin, small_end);
                big_vector.push_back(item);
                small_end = small_begin - 1;
            }
            else
            {
                new (small_end) T(item);
                ++small_end;
            }
        }

        void pop_back()
        {
            if (big()) return big_vector.pop_back();
            if (size() != 0)
            {
                (small_end - 1)->~T();
                --small_end;
                return;
            }
            throw std::range_error("Cannot pop_back empty ax::vector.");
        }

        T* erase(const T* iter)
        {
            if (big())
            {
                VAL pos = iter - big_vector.data();
                VAL& iter = big_vector.begin() + pos;
                return &*big_vector.erase(iter);
            }
            small_end = std::remove(small_begin, small_end, *iter);
            return small_end;
        }

        T& at(std::size_t pos)
        {
            if (big()) return big_vector.at(pos);
            if (pos < size()) return *(small_begin + pos);
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        const T& at(std::size_t pos) const
        {
            return const_cast<ax::vector<T, A, N>*>(this)->at(pos);
        }

        void assign(std::size_t pos, const T& item)
        {
            if (big()) return big_vector.assign(pos, item);
            if (pos < size()) return small_begin + pos;
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        T& front()
        {
            if (big()) return big_vector.front();
            if (size() > 0) return *small_begin;
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        T& back()
        {
            if (big()) return big_vector.back();
            if (size() > 0) return *(small_end - 1);
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        std::size_t capacity() const
        {
            if (big()) return big_vector.capacity();
            return N;
        }

        void clear()
        {
            if (big()) big_vector.clear();
            else small_end = small_begin;
        }

        T* data()
        {
            if (big()) return big_vector.data();
            return small_begin;
        }

        const T* data() const
        {
            return const_cast<ax::vector<T, A, N>*>(this)->data();
        }

        std::size_t size() const
        {
            return end() - begin();
        }

        inline bool big() const
        {
            return small_end < small_begin;
        }

    private:

        T small_begin[N];
        T* small_end;
        std::vector<T, A> big_vector;
    };
}

#endif
<commit_msg>Made ax::vector::small_end nullable.<commit_after>#ifndef IMPL_AX_VECTOR_HPP
#define IMPL_AX_VECTOR_HPP

#include <cstddef>
#include <algorithm>
#include <vector>
#include <memory>

#include "prelude.hpp"

namespace ax
{
    // A vector with small size optimization.
    template<typename T, typename A = std::allocator<T>, std::size_t N = 4>
    class vector
    {
    public:

        CONSTRAINT(vector);
        using value_type = T;
        using size_type = std::size_t;
        using iterator = T*;
        using const_iterator = const T*;
        using allocator = A; // TODO: see if this is a meaningful trait name
        template<typename T2, typename A2, std::size_t N2>
        using reify = ax::vector<T2, A2, N2>;

        vector() : vector({ }) { }

        vector(std::initializer_list<T> il) :
            vector(il.begin(), il.end()) { }

        vector(const T* begin, const T* end)
        {
            VAR size = static_cast<std::size_t>(end - begin);
            if (size > N)
            {
                small_end = nullptr;
                big_vector.insert(big_vector.begin(), begin, end);
            }
            else
            {
                small_end = small_begin;
                for (VAR i = 0_z; i < N && begin != end; ++i)
                {
                    *small_end = *begin;
                    ++small_end;
                    ++begin;
                }
            }
        }

        vector(const ax::vector<T, A, N>& that)
        {
            if (that.big())
            {
                small_end = nullptr;
                big_vector = that.big_vector;
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        vector(ax::vector<T, A, N>&& that)
        {
            if (that.big())
            {
                small_end = nullptr;
                big_vector = std::move(that.big_vector);
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        ~vector() = default;

        ax::vector<T, A, N>& operator=(const ax::vector<T, A, N>& that)
        {
            big_vector = that.big_vector;
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        ax::vector<T, A, N>& operator=(ax::vector<T, A, N>&& that)
        {
            big_vector = std::move(that.big_vector);
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        bool operator==(const ax::vector<T, A, N>& that) const
        {
            VAL size = this->size();
            if (size > N) return big_vector == that.big_vector;
            VAR result = true;
            for (VAR i = 0_z; result && i < size; ++i)
                result = small_begin[i] == that.small_begin[i];
            return result;
        }

        bool operator!=(const ax::vector<T, A, N>& that) const
        {
            return !(*this == that);
        }

        T* begin() { return big() ? big_vector.data() : small_begin; }
        T* end() { return big() ? big_vector.data() + big_vector.size() : small_end; }
        const T* cbegin() const { return const_cast<ax::vector<T, A, N>*>(this)->begin(); }
        const T* cend() const { return const_cast<ax::vector<T, A, N>*>(this)->end(); }
        const T* begin() const { return cbegin(); }
        const T* end() const { return cend(); }

        void push_back(const T& item)
        {
            if (big())
            {
                big_vector.push_back(item);
            }
            else if (size() == N)
            {
                big_vector.insert(big_vector.begin(), small_begin, small_end);
                big_vector.push_back(item);
                small_end = nullptr;
            }
            else
            {
                new (small_end) T(item);
                ++small_end;
            }
        }

        void pop_back()
        {
            if (big()) return big_vector.pop_back();
            if (size() != 0)
            {
                (small_end - 1)->~T();
                --small_end;
                return;
            }
            throw std::range_error("Cannot pop_back empty ax::vector.");
        }

        T* erase(const T* iter)
        {
            if (big())
            {
                VAL pos = iter - big_vector.data();
                VAL& iter = big_vector.begin() + pos;
                return &*big_vector.erase(iter);
            }
            small_end = std::remove(small_begin, small_end, *iter);
            return small_end;
        }

        T& at(std::size_t pos)
        {
            if (big()) return big_vector.at(pos);
            if (pos < size()) return *(small_begin + pos);
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        const T& at(std::size_t pos) const
        {
            return const_cast<ax::vector<T, A, N>*>(this)->at(pos);
        }

        void assign(std::size_t pos, const T& item)
        {
            if (big()) return big_vector.assign(pos, item);
            if (pos < size()) return small_begin + pos;
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        T& front()
        {
            if (big()) return big_vector.front();
            if (size() > 0) return *small_begin;
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        T& back()
        {
            if (big()) return big_vector.back();
            if (size() > 0) return *(small_end - 1);
            throw std::out_of_range("ax::vector indexed out of range.");
        }

        std::size_t capacity() const
        {
            if (big()) return big_vector.capacity();
            return N;
        }

        void clear()
        {
            if (big()) big_vector.clear();
            else small_end = small_begin;
        }

        T* data()
        {
            if (big()) return big_vector.data();
            return small_begin;
        }

        const T* data() const
        {
            return const_cast<ax::vector<T, A, N>*>(this)->data();
        }

        std::size_t size() const
        {
            return end() - begin();
        }

        inline bool big() const
        {
            return !small_end;
        }

    private:

        T small_begin[N];
        T* small_end;
        std::vector<T, A> big_vector;
    };
}

#endif
<|endoftext|>


<commit_before>/*
     This file is part of libhttpserver
     Copyright (C) 2011 Sebastiano Merlino

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

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

#if !defined (_HTTPSERVER_HPP_INSIDE_) && !defined (HTTPSERVER_COMPILATION)
#error "Only <httpserver.hpp> or <httpserverpp> can be included directly."
#endif

#ifndef _BINDERS_HPP_
#define _BINDERS_HPP_

namespace httpserver {
namespace details
{
    namespace binders
    {
        class generic_class;
        const int MEMFUNC_SIZE = sizeof(void (generic_class::*)());

        template<int N>
        struct converter
        {
            template<typename X,
                typename func_type,
                typename generic_mem_func_type>
            inline static generic_class* convert(
                    X* pmem,
                    func_type func,
                    generic_mem_func_type &bound
            )
            {
                typedef char ERROR_member_pointer_not_supported[N-100];
                return 0;
            }
        };

        template<>
        struct converter<MEMFUNC_SIZE>
        {
            template<typename X,
                typename func_type,
                typename generic_mem_func_type>
            inline static generic_class* convert(
                    X* pmem,
                    func_type func,
                    generic_mem_func_type &bound
            )
            {
                bound = reinterpret_cast<generic_mem_func_type>(func);
                return reinterpret_cast<generic_class*>(pmem);
            }
        };

        template<typename generic_mem,
            typename static_function,
            typename void_static_function>
        class binder
        {
            private:
                typedef void (generic_class::*generic_mem_fun)();
                typedef void (*generic_mem_ptr)();

                generic_class *pmem;
                generic_mem_fun _pfunc;
                generic_mem_ptr _spfunc;

            public:
                binder()
                {
                }

                binder(const binder& o):
                    pmem(o.pmem),
                    _pfunc(o._pfunc),
                    _spfunc(o._spfunc)
                {
                }

                template<typename X, typename Y>
                binder(X* pmem, Y fun):
                    pmem(converter<sizeof(fun)>::convert(pmem, fun, _pfunc)),
                    _spfunc(0)
                {
                }

                template<class DC, class parent_invoker>
                binder(DC* pp, parent_invoker invoker, static_function fun):
                    pmem(converter<sizeof(invoker)>::convert(pp, invoker, _pfunc)),
                    _spfunc(reinterpret_cast<generic_mem_ptr>(fun))
                {
                }

                inline generic_class* exec() const
                {
                    return pmem;
                }
                inline generic_mem get_mem_ptr() const
                {
                    return reinterpret_cast<const generic_mem>(_pfunc);
                }
                inline void_static_function get_static_func() const
                {
                    return reinterpret_cast<void_static_function>(_spfunc);
                }
        };

        template<typename PAR1, typename RET_TYPE=void>
        class functor_one
        {
            private:
                typedef RET_TYPE (*static_function)(PAR1 p1);
                typedef RET_TYPE (*void_static_function)(PAR1 p1);
                typedef RET_TYPE (generic_class::*generic_mem)(PAR1 p1);
                typedef binder<generic_mem,
                        static_function, void_static_function> binder_type;
                binder_type _binder;

                RET_TYPE exec_static(PAR1 p1) const
                {
                    return (*(_binder.get_static_func()))(p1);
                }

                functor_one& operator=(const functor_one&)
                {
                    return *this;
                }
            public:
                typedef functor_one type;
                functor_one() { }

                template <typename X, typename Y>
                functor_one(Y* pmem, RET_TYPE(X::*func)(PAR1 p1) ):
                    _binder(reinterpret_cast<X*>(pmem), func)
                {
                }

                functor_one(RET_TYPE(*func)(PAR1 p1) ):
                    _binder(this, &functor_one::exec_static, func)
                {
                }

                RET_TYPE operator() (PAR1 p1) const
                {
                    return (_binder.exec()->*(_binder.get_mem_ptr()))(p1);
                }
        };

        template<typename PAR1, typename PAR2, typename RET_TYPE=void>
        class functor_two
        {
            private:
                typedef RET_TYPE (*static_function)(PAR1 p1, PAR2 p2);
                typedef RET_TYPE (*void_static_function)(PAR1 p1, PAR2 p2);

                typedef RET_TYPE
                    (generic_class::*generic_mem)(PAR1 p1, PAR2 p2);

                typedef binder<
                    generic_mem, static_function, void_static_function
                > binder_type;

                binder_type _binder;

                RET_TYPE exec_static(PAR1 p1, PAR2 p2) const
                {
                    return (*(_binder.get_static_func()))(p1, p2);
                }
            public:
                typedef functor_two type;
                functor_two() { }

                functor_two(const functor_two& o):
                    _binder(o._binder)
                {
                }

                template <typename X, typename Y>
                functor_two(Y* pmem, RET_TYPE(X::*func)(PAR1 p1, PAR2 p2) ):
                    _binder(reinterpret_cast<X*>(pmem), func)
                {
                }
                functor_two(RET_TYPE(*func)(PAR1 p1, PAR2 p2) ):
                    _binder(this, &functor_two::exec_static, func)
                {
                }

                RET_TYPE operator() (PAR1 p1, PAR2 p2) const
                {
                    return (_binder.exec()->*(_binder.get_mem_ptr()))(p1, p2);
                }
        };
    }
}}

#endif
<commit_msg>Removed useless typedef<commit_after>/*
     This file is part of libhttpserver
     Copyright (C) 2011 Sebastiano Merlino

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

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

#if !defined (_HTTPSERVER_HPP_INSIDE_) && !defined (HTTPSERVER_COMPILATION)
#error "Only <httpserver.hpp> or <httpserverpp> can be included directly."
#endif

#ifndef _BINDERS_HPP_
#define _BINDERS_HPP_

namespace httpserver {
namespace details
{
    namespace binders
    {
        class generic_class;
        const int MEMFUNC_SIZE = sizeof(void (generic_class::*)());

        template<int N>
        struct converter
        {
            template<typename X,
                typename func_type,
                typename generic_mem_func_type>
            inline static generic_class* convert(
                    X* pmem,
                    func_type func,
                    generic_mem_func_type &bound
            )
            {
                return 0;
            }
        };

        template<>
        struct converter<MEMFUNC_SIZE>
        {
            template<typename X,
                typename func_type,
                typename generic_mem_func_type>
            inline static generic_class* convert(
                    X* pmem,
                    func_type func,
                    generic_mem_func_type &bound
            )
            {
                bound = reinterpret_cast<generic_mem_func_type>(func);
                return reinterpret_cast<generic_class*>(pmem);
            }
        };

        template<typename generic_mem,
            typename static_function,
            typename void_static_function>
        class binder
        {
            private:
                typedef void (generic_class::*generic_mem_fun)();
                typedef void (*generic_mem_ptr)();

                generic_class *pmem;
                generic_mem_fun _pfunc;
                generic_mem_ptr _spfunc;

            public:
                binder()
                {
                }

                binder(const binder& o):
                    pmem(o.pmem),
                    _pfunc(o._pfunc),
                    _spfunc(o._spfunc)
                {
                }

                template<typename X, typename Y>
                binder(X* pmem, Y fun):
                    pmem(converter<sizeof(fun)>::convert(pmem, fun, _pfunc)),
                    _spfunc(0)
                {
                }

                template<class DC, class parent_invoker>
                binder(DC* pp, parent_invoker invoker, static_function fun):
                    pmem(converter<sizeof(invoker)>::convert(pp, invoker, _pfunc)),
                    _spfunc(reinterpret_cast<generic_mem_ptr>(fun))
                {
                }

                inline generic_class* exec() const
                {
                    return pmem;
                }
                inline generic_mem get_mem_ptr() const
                {
                    return reinterpret_cast<const generic_mem>(_pfunc);
                }
                inline void_static_function get_static_func() const
                {
                    return reinterpret_cast<void_static_function>(_spfunc);
                }
        };

        template<typename PAR1, typename RET_TYPE=void>
        class functor_one
        {
            private:
                typedef RET_TYPE (*static_function)(PAR1 p1);
                typedef RET_TYPE (*void_static_function)(PAR1 p1);
                typedef RET_TYPE (generic_class::*generic_mem)(PAR1 p1);
                typedef binder<generic_mem,
                        static_function, void_static_function> binder_type;
                binder_type _binder;

                RET_TYPE exec_static(PAR1 p1) const
                {
                    return (*(_binder.get_static_func()))(p1);
                }

                functor_one& operator=(const functor_one&)
                {
                    return *this;
                }
            public:
                typedef functor_one type;
                functor_one() { }

                template <typename X, typename Y>
                functor_one(Y* pmem, RET_TYPE(X::*func)(PAR1 p1) ):
                    _binder(reinterpret_cast<X*>(pmem), func)
                {
                }

                functor_one(RET_TYPE(*func)(PAR1 p1) ):
                    _binder(this, &functor_one::exec_static, func)
                {
                }

                RET_TYPE operator() (PAR1 p1) const
                {
                    return (_binder.exec()->*(_binder.get_mem_ptr()))(p1);
                }
        };

        template<typename PAR1, typename PAR2, typename RET_TYPE=void>
        class functor_two
        {
            private:
                typedef RET_TYPE (*static_function)(PAR1 p1, PAR2 p2);
                typedef RET_TYPE (*void_static_function)(PAR1 p1, PAR2 p2);

                typedef RET_TYPE
                    (generic_class::*generic_mem)(PAR1 p1, PAR2 p2);

                typedef binder<
                    generic_mem, static_function, void_static_function
                > binder_type;

                binder_type _binder;

                RET_TYPE exec_static(PAR1 p1, PAR2 p2) const
                {
                    return (*(_binder.get_static_func()))(p1, p2);
                }
            public:
                typedef functor_two type;
                functor_two() { }

                functor_two(const functor_two& o):
                    _binder(o._binder)
                {
                }

                template <typename X, typename Y>
                functor_two(Y* pmem, RET_TYPE(X::*func)(PAR1 p1, PAR2 p2) ):
                    _binder(reinterpret_cast<X*>(pmem), func)
                {
                }
                functor_two(RET_TYPE(*func)(PAR1 p1, PAR2 p2) ):
                    _binder(this, &functor_two::exec_static, func)
                {
                }

                RET_TYPE operator() (PAR1 p1, PAR2 p2) const
                {
                    return (_binder.exec()->*(_binder.get_mem_ptr()))(p1, p2);
                }
        };
    }
}}

#endif
<|endoftext|>


<commit_before>#include "portroutingwidget.h"

#include <sstream>

PortRoutingWidget::PortRoutingWidget(QWidget *parent, int numDinPorts)
    : QWidget(parent), numDinPorts(numDinPorts) {
  createWidgets();
}

void PortRoutingWidget::createWidgets() {
  layout = new QGridLayout(this);
  for (int i = 0; i < numDinPorts; ++i) {
    std::stringstream s;
    s << (i + 1);
    PortButton *b =
        new PortButton(i, QString(s.str().c_str()), PortButton::MIDI, this);
    layout->addWidget(b, 0, i);
  }
  for (int i = 0; i < 10; ++i) {
    std::stringstream s;
    s << (i + 1);
    PortButton *b = new PortButton(i, QString(s.str().c_str()),
                                   PortButton::USB_DEVICE, this);
    layout->addWidget(b, 1, i);
  }
  for (int i = 0; i < 5; ++i) {
    std::stringstream s;
    s << (i + 1);
    PortButton *b =
        new PortButton(i, QString(s.str().c_str()), PortButton::ETH, this);
    layout->addWidget(b, 2, i);
  }
}

void PortRoutingWidget::setupWidgets() {}

void PortRoutingWidget::setupLayout() { setLayout(layout); }

void PortRoutingWidget::setData() {}

void PortRoutingWidget::createConnections() {}
<commit_msg>use MidiPortType from RetSetMidiPortInfo<commit_after>#include "portroutingwidget.h"

#include <sstream>

PortRoutingWidget::PortRoutingWidget(QWidget *parent, int numDinPorts)
    : QWidget(parent), numDinPorts(numDinPorts) {
  createWidgets();
}

void PortRoutingWidget::createWidgets() {
  layout = new QGridLayout(this);
  for (int i = 0; i < numDinPorts; ++i) {
    std::stringstream s;
    s << (i + 1);
		PortButton *b = new PortButton(i, QString(s.str().c_str()), DIN, this);
    layout->addWidget(b, 0, i);
  }
  for (int i = 0; i < 10; ++i) {
    std::stringstream s;
    s << (i + 1);
		PortButton *b =
				new PortButton(i, QString(s.str().c_str()), USB_DEVICE, this);
    layout->addWidget(b, 1, i);
  }
  for (int i = 0; i < 5; ++i) {
    std::stringstream s;
    s << (i + 1);
		PortButton *b = new PortButton(i, QString(s.str().c_str()), ETHERNET, this);
    layout->addWidget(b, 2, i);
  }
}

void PortRoutingWidget::setupWidgets() {}

void PortRoutingWidget::setupLayout() { setLayout(layout); }

void PortRoutingWidget::setData() {}

void PortRoutingWidget::createConnections() {}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FakeCamera.h"

#include "../graphics/Pixel8.h"
#include "../graphics/Filterfill.h"
#include "../graphics/Filterfillrect.h"
#include "../graphics/Filtergrayscale.h"

#include "../base/TimeSource.h"
#include "../base/Exception.h"
#include "../base/Logger.h"

#include <Magick++.h>

using namespace std;

namespace avg {

FakeCamera::FakeCamera(PixelFormat camPF, PixelFormat destPF)
    : Camera(camPF, destPF),
      m_pBmpQ(new std::queue<BitmapPtr>()),
      m_bIsOpen(false)
{
    m_ImgSize = IntPoint(640, 480);
}

FakeCamera::FakeCamera(std::vector<std::string> &pictures)
    : Camera(I8, I8),
      m_pBmpQ(new std::queue<BitmapPtr>()),
      m_bIsOpen(false)
{
    m_ImgSize = IntPoint(640, 480);
    for(std::vector<std::string>::iterator it=pictures.begin();it!=pictures.end();++it){
        try {
            BitmapPtr pBmp (new Bitmap(*it));
            FilterGrayscale().applyInPlace(pBmp);
            m_ImgSize = pBmp->getSize();
            m_pBmpQ->push(pBmp);
        } catch (Exception& ex) {
            AVG_TRACE(Logger::ERROR, ex.GetStr());
            throw;
        } catch (Magick::Exception & ex) {
            AVG_TRACE(Logger::ERROR, ex.what());
            throw;
        }
    }
}

FakeCamera::~FakeCamera()
{
}

void FakeCamera::open()
{
    m_bIsOpen = true;
}

void FakeCamera::close()
{
    m_bIsOpen = false;
}

IntPoint FakeCamera::getImgSize()
{
    return m_ImgSize;
}

BitmapPtr FakeCamera::getImage(bool bWait)
{
    msleep(100);
    if (!m_bIsOpen || !bWait || m_pBmpQ->empty()) {
        return BitmapPtr();
    } else {
        BitmapPtr pBmp = m_pBmpQ->front();
        m_pBmpQ->pop();
        return pBmp;
    }
}

bool FakeCamera::isCameraAvailable()
{
    return true;
}

const string& FakeCamera::getDevice() const
{
    static string sDeviceName = "FakeCamera";
    return sDeviceName;
}

const std::string& FakeCamera::getDriverName() const
{
    static string sDriverName = "FakeCameraDriver";
    return sDriverName;
}

double FakeCamera::getFrameRate() const
{
    return 60;
}

const string& FakeCamera::getMode() const
{
    static string sMode = "FakeCamera";
    return sMode;
}

int FakeCamera::getFeature(CameraFeature Feature) const
{
    return 0;
}

void FakeCamera::setFeature(CameraFeature Feature, int Value, bool bIgnoreOldValue)
{
}

void FakeCamera::setFeatureOneShot(CameraFeature Feature)
{
}

int FakeCamera::getWhitebalanceU() const
{
    return 0;
}

int FakeCamera::getWhitebalanceV() const
{
    return 0;
}

void FakeCamera::setWhitebalance(int u, int v, bool bIgnoreOldValue)
{
}

}

<commit_msg>Fixed 100 ms delay per frame when using FakeCamera.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FakeCamera.h"

#include "../graphics/Pixel8.h"
#include "../graphics/Filterfill.h"
#include "../graphics/Filterfillrect.h"
#include "../graphics/Filtergrayscale.h"

#include "../base/TimeSource.h"
#include "../base/Exception.h"
#include "../base/Logger.h"

#include <Magick++.h>

using namespace std;

namespace avg {

FakeCamera::FakeCamera(PixelFormat camPF, PixelFormat destPF)
    : Camera(camPF, destPF),
      m_pBmpQ(new std::queue<BitmapPtr>()),
      m_bIsOpen(false)
{
    m_ImgSize = IntPoint(640, 480);
}

FakeCamera::FakeCamera(std::vector<std::string> &pictures)
    : Camera(I8, I8),
      m_pBmpQ(new std::queue<BitmapPtr>()),
      m_bIsOpen(false)
{
    m_ImgSize = IntPoint(640, 480);
    for(std::vector<std::string>::iterator it=pictures.begin();it!=pictures.end();++it){
        try {
            BitmapPtr pBmp (new Bitmap(*it));
            FilterGrayscale().applyInPlace(pBmp);
            m_ImgSize = pBmp->getSize();
            m_pBmpQ->push(pBmp);
        } catch (Exception& ex) {
            AVG_TRACE(Logger::ERROR, ex.GetStr());
            throw;
        } catch (Magick::Exception & ex) {
            AVG_TRACE(Logger::ERROR, ex.what());
            throw;
        }
    }
}

FakeCamera::~FakeCamera()
{
}

void FakeCamera::open()
{
    m_bIsOpen = true;
}

void FakeCamera::close()
{
    m_bIsOpen = false;
}

IntPoint FakeCamera::getImgSize()
{
    return m_ImgSize;
}

BitmapPtr FakeCamera::getImage(bool bWait)
{
    if (bWait) {
        msleep(100);
    }
    if (!m_bIsOpen || !bWait || m_pBmpQ->empty()) {
        return BitmapPtr();
    } else {
        BitmapPtr pBmp = m_pBmpQ->front();
        m_pBmpQ->pop();
        return pBmp;
    }
}

bool FakeCamera::isCameraAvailable()
{
    return true;
}

const string& FakeCamera::getDevice() const
{
    static string sDeviceName = "FakeCamera";
    return sDeviceName;
}

const std::string& FakeCamera::getDriverName() const
{
    static string sDriverName = "FakeCameraDriver";
    return sDriverName;
}

double FakeCamera::getFrameRate() const
{
    return 60;
}

const string& FakeCamera::getMode() const
{
    static string sMode = "FakeCamera";
    return sMode;
}

int FakeCamera::getFeature(CameraFeature Feature) const
{
    return 0;
}

void FakeCamera::setFeature(CameraFeature Feature, int Value, bool bIgnoreOldValue)
{
}

void FakeCamera::setFeatureOneShot(CameraFeature Feature)
{
}

int FakeCamera::getWhitebalanceU() const
{
    return 0;
}

int FakeCamera::getWhitebalanceV() const
{
    return 0;
}

void FakeCamera::setWhitebalance(int u, int v, bool bIgnoreOldValue)
{
}

}

<|endoftext|>