<commit_before>//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "ExtruderTrain.h"
#include "FffGcodeWriter.h"
#include "InsetOrderOptimizer.h"
#include "LayerPlan.h"
#include "utils/logoutput.h"
#include "WallToolPaths.h"

namespace cura
{

InsetOrderOptimizer::InsetOrderOptimizer(const FffGcodeWriter& gcode_writer, const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const int extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const VariableWidthPaths& paths, unsigned int layer_nr) :
    gcode_writer(gcode_writer),
    storage(storage),
    gcode_layer(gcode_layer),
    mesh(mesh),
    extruder_nr(extruder_nr),
    mesh_config(mesh_config),
    paths(paths),
    layer_nr(layer_nr),
    z_seam_config(mesh.settings.get<EZSeamType>("z_seam_type"), mesh.getZSeamHint(), mesh.settings.get<EZSeamCornerPrefType>("z_seam_corner"), mesh.settings.get<coord_t>("wall_line_width_0") * 2),
    added_something(false),
    retraction_region_calculated(false)
{
}

bool InsetOrderOptimizer::optimize(const WallType& wall_type)
{
    // Settings & configs:
    const GCodePathConfig& skin_or_infill_config = wall_type == WallType::EXTRA_SKIN ? mesh_config.skin_config : mesh_config.infill_config[0];
    const bool do_outer_wall = wall_type == WallType::OUTER_WALL;
    const GCodePathConfig& inset_0_non_bridge_config = do_outer_wall ? mesh_config.inset0_config : skin_or_infill_config;
    const GCodePathConfig& inset_X_non_bridge_config = do_outer_wall ? mesh_config.insetX_config : skin_or_infill_config;
    const GCodePathConfig& inset_0_bridge_config = do_outer_wall ? mesh_config.bridge_inset0_config : skin_or_infill_config;
    const GCodePathConfig& inset_X_bridge_config = do_outer_wall ? mesh_config.bridge_insetX_config : skin_or_infill_config;

    const size_t wall_0_extruder_nr = mesh.settings.get<ExtruderTrain&>("wall_0_extruder_nr").extruder_nr;
    const size_t wall_x_extruder_nr = mesh.settings.get<ExtruderTrain&>("wall_x_extruder_nr").extruder_nr;
    const size_t top_bottom_extruder_nr = mesh.settings.get<ExtruderTrain&>("top_bottom_extruder_nr").extruder_nr;
    const size_t infill_extruder_nr = mesh.settings.get<ExtruderTrain&>("infill_extruder_nr").extruder_nr;

    const bool pack_by_inset = !mesh.settings.get<bool>("optimize_wall_printing_order");
    const InsetDirection inset_direction = mesh.settings.get<InsetDirection>("inset_direction");
    const bool center_last = inset_direction == InsetDirection::CENTER_LAST;

    //Bin the insets in order to print the inset indices together, and to optimize the order of each bin to reduce travels.
    std::set<size_t> bins_with_index_zero_insets;
    BinJunctions insets = variableWidthPathToBinJunctions(paths, pack_by_inset, center_last, &bins_with_index_zero_insets);

    size_t start_inset;
    size_t end_inset;
    int direction;
    //If the entire wall is printed with the current extruder, print all of it.
    if((wall_type == WallType::OUTER_WALL && wall_0_extruder_nr == wall_x_extruder_nr && wall_x_extruder_nr == extruder_nr) ||
            (wall_type == WallType::EXTRA_SKIN && extruder_nr == top_bottom_extruder_nr) ||
            (wall_type == WallType::EXTRA_INFILL && extruder_nr == infill_extruder_nr))
    {
        //If printing the outer inset first, start with the lowest inset.
        //Otherwise start with the highest inset and iterate backwards.
        if(inset_direction == InsetDirection::OUTSIDE_IN)
        {
            start_inset = 0;
            end_inset = insets.size();
            direction = 1;
        }
        else //INSIDE_OUT or CENTER_LAST.
        {
            start_inset = insets.size() - 1;
            end_inset = -1;
            direction = -1;
        }
    }
    //If the wall is partially printed with the current extruder, print the correct part.
    else if(wall_type == WallType::OUTER_WALL && wall_0_extruder_nr != wall_x_extruder_nr)
    {
        //If the wall_0 and wall_x extruders are different, then only include the insets that should be printed by the
        //current extruder_nr.
        if(extruder_nr == wall_0_extruder_nr)
        {
            start_inset = 0;
            end_inset = 1; // Ignore inner walls
            direction = 1;
        }
        else if(extruder_nr == wall_x_extruder_nr)
        {
            start_inset = insets.size() - 1;
            end_inset = 0; // Ignore outer wall
            direction = -1;
        }
        else
        {
            return added_something;
        }
    }
    else //The wall is not printed with this extruder, not even in part. Don't print anything then.
    {
        return added_something;
    }

    //Add all of the insets one by one.
    constexpr Ratio flow = 1.0_r;
    const bool retract_before_outer_wall = mesh.settings.get<bool>("travel_retract_before_outer_wall");
    const coord_t wall_0_wipe_dist = mesh.settings.get<coord_t>("wall_0_wipe_dist");
    for(size_t inset = start_inset; inset != end_inset; inset += direction)
    {
        if(insets[inset].empty())
        {
            continue; //Don't switch extruders either, etc.
        }
        added_something = true;
        gcode_writer.setExtruder_addPrime(storage, gcode_layer, extruder_nr);
        gcode_layer.setIsInside(true); //Going to print walls, which are always inside.
        ZSeamConfig z_seam_config(mesh.settings.get<EZSeamType>("z_seam_type"), mesh.getZSeamHint(), mesh.settings.get<EZSeamCornerPrefType>("z_seam_corner"), mesh.settings.get<coord_t>("wall_line_width_0") * 2);

        const bool alternate_direction_modifier = inset % 2 == 0;
        if(bins_with_index_zero_insets.count(inset) > 0) //Print using outer wall config.
        {
            gcode_layer.addWalls(insets[inset], mesh.settings, inset_0_non_bridge_config, inset_0_bridge_config, z_seam_config, wall_0_wipe_dist, flow, retract_before_outer_wall, alternate_direction_modifier);
        }
        else
        {
            gcode_layer.addWalls(insets[inset], mesh.settings, inset_X_non_bridge_config, inset_X_bridge_config, z_seam_config, 0, flow, false, alternate_direction_modifier);
        }
    }
    return added_something;
}

size_t InsetOrderOptimizer::getOuterRegionId(const VariableWidthPaths& toolpaths, size_t& out_max_region_id)
{
    // Polygons show up here one by one, so there are always only a) the outer lines and b) the lines that are part of the holes.
    // Therefore, the outer-regions' lines will always have the region-id that is larger then all of the other ones.

    // First, build the bounding boxes:
    std::map<size_t, AABB> region_ids_to_bboxes; //Use a sorted map, ordered by region_id, so that we can find the largest region_id quickly.
    for (const VariableWidthLines& path : toolpaths)
    {
        for (const ExtrusionLine& line : path)
        {
            AABB& aabb = region_ids_to_bboxes[line.region_id]; // Empty AABBs are default initialized when region_ids are encountered for the first time.
            for (const auto& junction : line.junctions)
            {
                aabb.include(junction.p);
            }
        }
    }

    // Then, the largest of these will be the one that's needed for the outer region, the others' all belong to hole regions:
    AABB outer_bbox;
    size_t outer_region_id = 0; // Region-ID 0 is reserved for 'None'.
    for (const auto& region_id_bbox_pair : region_ids_to_bboxes)
    {
        if (region_id_bbox_pair.second.contains(outer_bbox))
        {
            outer_bbox = region_id_bbox_pair.second;
            outer_region_id = region_id_bbox_pair.first;
        }
    }

    // Maximum Region-ID (using the ordering of the map)
    out_max_region_id = region_ids_to_bboxes.empty() ? 0 : region_ids_to_bboxes.rbegin()->first;
    return outer_region_id;
}

BinJunctions InsetOrderOptimizer::variableWidthPathToBinJunctions(const VariableWidthPaths& toolpaths, const bool pack_regions_by_inset,
                                                                  const bool center_last, std::set<size_t>* p_bins_with_index_zero_insets,
                                                                  const bool alternate_inset_direction, const bool reverse_initial_inset)
{
    // Find the largest inset-index:
    size_t max_inset_index = 0;
    for (const VariableWidthLines& path : toolpaths)
    {
        max_inset_index = std::max(path.front().inset_idx, max_inset_index);
    }

    // Find which regions are associated with the outer-outer walls (which region is the one the rest is holes inside of):
    size_t max_region_id = 0;
    const size_t outer_region_id = getOuterRegionId(toolpaths, max_region_id);

    //Since we're (optionally!) splitting off in the outer and inner regions, it may need twice as many bins as inset-indices.
    //Add two extra bins for the center-paths, if they need to be stored separately. One bin for inner and one for outer walls.
    const size_t max_bin = (pack_regions_by_inset ? (max_region_id * 2) + 2 : (max_inset_index + 1) * 2) + center_last * 2;
    BinJunctions insets(max_bin + 1);
    for (const VariableWidthLines& path : toolpaths)
    {
        if (path.empty()) // Don't bother printing these.
        {
            continue;
        }
        const size_t inset_index = path.front().inset_idx;

        // Convert list of extrusion lines to vectors of extrusion junctions, and add those to the binned insets.
        for (const ExtrusionLine& line : path)
        {
            // Sort into the right bin, ...
            size_t bin_index;
            const bool in_hole_region = line.region_id != outer_region_id && line.region_id != 0;
            if(center_last && line.is_odd)
            {
                bin_index = inset_index > 0;
            }
            else if(pack_regions_by_inset)
            {
                bin_index = std::min(inset_index, static_cast<size_t>(1)) + 2 * (in_hole_region ? line.region_id : 0) + center_last * 2;
            }
            else
            {
                bin_index = inset_index + (in_hole_region ? (max_inset_index + 1) : 0) + center_last * 2;
            }
            insets[bin_index].emplace_back(line.junctions.begin(), line.junctions.end());

            // Collect all bins that have zero-inset indices in them, if needed:
            if (inset_index == 0 && p_bins_with_index_zero_insets != nullptr)
            {
                p_bins_with_index_zero_insets->insert(bin_index);
            }
        }
    }

    if (alternate_inset_direction)
    {
        bool alternate_inset_print_direction = reverse_initial_inset;
        for (PathJunctions &paths : insets)
        {
            for (LineJunctions &line: paths)
            {
                if (alternate_inset_print_direction)
                {
                    std::reverse(line.begin(), line.end());
                }
            }
            if(alternate_inset_print_direction)
            {
                std::reverse(paths.begin(), paths.end());
            }
            alternate_inset_print_direction = !alternate_inset_print_direction;
        }
    }

    return insets;
}

}//namespace cura
<commit_msg>Fix alternating print direction of insets<commit_after>//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "ExtruderTrain.h"
#include "FffGcodeWriter.h"
#include "InsetOrderOptimizer.h"
#include "LayerPlan.h"
#include "utils/logoutput.h"
#include "WallToolPaths.h"

namespace cura
{

InsetOrderOptimizer::InsetOrderOptimizer(const FffGcodeWriter& gcode_writer, const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const int extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const VariableWidthPaths& paths, unsigned int layer_nr) :
    gcode_writer(gcode_writer),
    storage(storage),
    gcode_layer(gcode_layer),
    mesh(mesh),
    extruder_nr(extruder_nr),
    mesh_config(mesh_config),
    paths(paths),
    layer_nr(layer_nr),
    z_seam_config(mesh.settings.get<EZSeamType>("z_seam_type"), mesh.getZSeamHint(), mesh.settings.get<EZSeamCornerPrefType>("z_seam_corner"), mesh.settings.get<coord_t>("wall_line_width_0") * 2),
    added_something(false),
    retraction_region_calculated(false)
{
}

bool InsetOrderOptimizer::optimize(const WallType& wall_type)
{
    // Settings & configs:
    const GCodePathConfig& skin_or_infill_config = wall_type == WallType::EXTRA_SKIN ? mesh_config.skin_config : mesh_config.infill_config[0];
    const bool do_outer_wall = wall_type == WallType::OUTER_WALL;
    const GCodePathConfig& inset_0_non_bridge_config = do_outer_wall ? mesh_config.inset0_config : skin_or_infill_config;
    const GCodePathConfig& inset_X_non_bridge_config = do_outer_wall ? mesh_config.insetX_config : skin_or_infill_config;
    const GCodePathConfig& inset_0_bridge_config = do_outer_wall ? mesh_config.bridge_inset0_config : skin_or_infill_config;
    const GCodePathConfig& inset_X_bridge_config = do_outer_wall ? mesh_config.bridge_insetX_config : skin_or_infill_config;

    const size_t wall_0_extruder_nr = mesh.settings.get<ExtruderTrain&>("wall_0_extruder_nr").extruder_nr;
    const size_t wall_x_extruder_nr = mesh.settings.get<ExtruderTrain&>("wall_x_extruder_nr").extruder_nr;
    const size_t top_bottom_extruder_nr = mesh.settings.get<ExtruderTrain&>("top_bottom_extruder_nr").extruder_nr;
    const size_t infill_extruder_nr = mesh.settings.get<ExtruderTrain&>("infill_extruder_nr").extruder_nr;

    const bool pack_by_inset = !mesh.settings.get<bool>("optimize_wall_printing_order");
    const InsetDirection inset_direction = mesh.settings.get<InsetDirection>("inset_direction");
    const bool center_last = inset_direction == InsetDirection::CENTER_LAST;

    //Bin the insets in order to print the inset indices together, and to optimize the order of each bin to reduce travels.
    std::set<size_t> bins_with_index_zero_insets;
    BinJunctions insets = variableWidthPathToBinJunctions(paths, pack_by_inset, center_last, &bins_with_index_zero_insets);

    size_t start_inset;
    size_t end_inset;
    int direction;
    //If the entire wall is printed with the current extruder, print all of it.
    if((wall_type == WallType::OUTER_WALL && wall_0_extruder_nr == wall_x_extruder_nr && wall_x_extruder_nr == extruder_nr) ||
            (wall_type == WallType::EXTRA_SKIN && extruder_nr == top_bottom_extruder_nr) ||
            (wall_type == WallType::EXTRA_INFILL && extruder_nr == infill_extruder_nr))
    {
        //If printing the outer inset first, start with the lowest inset.
        //Otherwise start with the highest inset and iterate backwards.
        if(inset_direction == InsetDirection::OUTSIDE_IN)
        {
            start_inset = 0;
            end_inset = insets.size();
            direction = 1;
        }
        else //INSIDE_OUT or CENTER_LAST.
        {
            start_inset = insets.size() - 1;
            end_inset = -1;
            direction = -1;
        }
    }
    //If the wall is partially printed with the current extruder, print the correct part.
    else if(wall_type == WallType::OUTER_WALL && wall_0_extruder_nr != wall_x_extruder_nr)
    {
        //If the wall_0 and wall_x extruders are different, then only include the insets that should be printed by the
        //current extruder_nr.
        if(extruder_nr == wall_0_extruder_nr)
        {
            start_inset = 0;
            end_inset = 1; // Ignore inner walls
            direction = 1;
        }
        else if(extruder_nr == wall_x_extruder_nr)
        {
            start_inset = insets.size() - 1;
            end_inset = 0; // Ignore outer wall
            direction = -1;
        }
        else
        {
            return added_something;
        }
    }
    else //The wall is not printed with this extruder, not even in part. Don't print anything then.
    {
        return added_something;
    }

    //Add all of the insets one by one.
    constexpr Ratio flow = 1.0_r;
    const bool retract_before_outer_wall = mesh.settings.get<bool>("travel_retract_before_outer_wall");
    const coord_t wall_0_wipe_dist = mesh.settings.get<coord_t>("wall_0_wipe_dist");
    for(size_t inset = start_inset; inset != end_inset; inset += direction)
    {
        if(insets[inset].empty())
        {
            continue; //Don't switch extruders either, etc.
        }
        added_something = true;
        gcode_writer.setExtruder_addPrime(storage, gcode_layer, extruder_nr);
        gcode_layer.setIsInside(true); //Going to print walls, which are always inside.
        ZSeamConfig z_seam_config(mesh.settings.get<EZSeamType>("z_seam_type"), mesh.getZSeamHint(), mesh.settings.get<EZSeamCornerPrefType>("z_seam_corner"), mesh.settings.get<coord_t>("wall_line_width_0") * 2);

        const bool alternate_direction_modifier = inset % 2 == 0;
        if(bins_with_index_zero_insets.count(inset) > 0) //Print using outer wall config.
        {
            gcode_layer.addWalls(insets[inset], mesh.settings, inset_0_non_bridge_config, inset_0_bridge_config, z_seam_config, wall_0_wipe_dist, flow, retract_before_outer_wall, alternate_direction_modifier);
        }
        else
        {
            gcode_layer.addWalls(insets[inset], mesh.settings, inset_X_non_bridge_config, inset_X_bridge_config, z_seam_config, 0, flow, false, alternate_direction_modifier);
        }
    }
    return added_something;
}

size_t InsetOrderOptimizer::getOuterRegionId(const VariableWidthPaths& toolpaths, size_t& out_max_region_id)
{
    // Polygons show up here one by one, so there are always only a) the outer lines and b) the lines that are part of the holes.
    // Therefore, the outer-regions' lines will always have the region-id that is larger then all of the other ones.

    // First, build the bounding boxes:
    std::map<size_t, AABB> region_ids_to_bboxes; //Use a sorted map, ordered by region_id, so that we can find the largest region_id quickly.
    for (const VariableWidthLines& path : toolpaths)
    {
        for (const ExtrusionLine& line : path)
        {
            AABB& aabb = region_ids_to_bboxes[line.region_id]; // Empty AABBs are default initialized when region_ids are encountered for the first time.
            for (const auto& junction : line.junctions)
            {
                aabb.include(junction.p);
            }
        }
    }

    // Then, the largest of these will be the one that's needed for the outer region, the others' all belong to hole regions:
    AABB outer_bbox;
    size_t outer_region_id = 0; // Region-ID 0 is reserved for 'None'.
    for (const auto& region_id_bbox_pair : region_ids_to_bboxes)
    {
        if (region_id_bbox_pair.second.contains(outer_bbox))
        {
            outer_bbox = region_id_bbox_pair.second;
            outer_region_id = region_id_bbox_pair.first;
        }
    }

    // Maximum Region-ID (using the ordering of the map)
    out_max_region_id = region_ids_to_bboxes.empty() ? 0 : region_ids_to_bboxes.rbegin()->first;
    return outer_region_id;
}

BinJunctions InsetOrderOptimizer::variableWidthPathToBinJunctions(const VariableWidthPaths& toolpaths, const bool pack_regions_by_inset,
                                                                  const bool center_last, std::set<size_t>* p_bins_with_index_zero_insets,
                                                                  const bool alternate_inset_direction, const bool reverse_initial_inset)
{
    // Find the largest inset-index:
    size_t max_inset_index = 0;
    for (const VariableWidthLines& path : toolpaths)
    {
        max_inset_index = std::max(path.front().inset_idx, max_inset_index);
    }

    // Find which regions are associated with the outer-outer walls (which region is the one the rest is holes inside of):
    size_t max_region_id = 0;
    const size_t outer_region_id = getOuterRegionId(toolpaths, max_region_id);

    //Since we're (optionally!) splitting off in the outer and inner regions, it may need twice as many bins as inset-indices.
    //Add two extra bins for the center-paths, if they need to be stored separately. One bin for inner and one for outer walls.
    const size_t max_bin = (pack_regions_by_inset ? (max_region_id * 2) + 2 : (max_inset_index + 1) * 2) + center_last * 2;
    BinJunctions insets(max_bin + 1);
    for (const VariableWidthLines& path : toolpaths)
    {
        if (path.empty()) // Don't bother printing these.
        {
            continue;
        }
        const size_t inset_index = path.front().inset_idx;

        const bool reverse_order = alternate_inset_direction && ((inset_index % 2 == 0) ^ reverse_initial_inset);

        // Convert list of extrusion lines to vectors of extrusion junctions, and add those to the binned insets.
        for (const ExtrusionLine& line : path)
        {
            // Sort into the right bin, ...
            size_t bin_index;
            const bool in_hole_region = line.region_id != outer_region_id && line.region_id != 0;
            if(center_last && line.is_odd)
            {
                bin_index = inset_index > 0;
            }
            else if(pack_regions_by_inset)
            {
                bin_index = std::min(inset_index, static_cast<size_t>(1)) + 2 * (in_hole_region ? line.region_id : 0) + center_last * 2;
            }
            else
            {
                bin_index = inset_index + (in_hole_region ? (max_inset_index + 1) : 0) + center_last * 2;
            }

            if (reverse_order)
            {
                insets[bin_index].emplace_back(line.junctions.rbegin(), line.junctions.rend());
            }
            else
            {
                insets[bin_index].emplace_back(line.junctions.begin(), line.junctions.end());
            }

            // Collect all bins that have zero-inset indices in them, if needed:
            if (inset_index == 0 && p_bins_with_index_zero_insets != nullptr)
            {
                p_bins_with_index_zero_insets->insert(bin_index);
            }
        }
    }

    return insets;
}

}//namespace cura
<|endoftext|>


<commit_before>#ifndef TOML11_REGION_H
#define TOML11_REGION_H
#include <memory>
#include <algorithm>
#include <iterator>
#include <string>

namespace toml
{
namespace detail
{

// location in a container, normally in a file content.
// shared_ptr points the resource that the iter points.
// it can be used not only for resource handling, but also error message.
template<typename Container>
struct location
{
    static_assert(std::is_same<char, typename Container::value_type>::value,"");
    using const_iterator = typename Container::const_iterator;

    location(Container cont)
      : source(std::make_shared<Container>(std::move(cont))),
        begin(source->cbegin()), iter(source->cbegin()), end(source->cend())
    {}
    location(const location&) = default;
    location(location&&)      = default;
    location& operator=(const location&) = default;
    location& operator=(location&&)      = default;
   ~location() = default;

    std::shared_ptr<const Container> source;
    const_iterator begin, iter, end;
};

// region in a container, normally in a file content.
// shared_ptr points the resource that the iter points.
// combinators returns this.
// it can be used not only for resource handling, but also error message.
template<typename Container>
struct region
{
    static_assert(std::is_same<char, typename Container::value_type>::value,"");
    using const_iterator = typename Container::const_iterator;

    region(const location<Container>& loc)
      : begin(loc.begin), first(loc.iter), last(loc.iter), end(loc.end),
        source(loc.source)
    {}
    region(location<Container>&& loc)
      : begin(loc.begin), first(loc.iter), last(loc.iter), end(loc.end),
        source(std::move(loc.source))
    {}

    region(const location<Container>& loc, const_iterator f, const_iterator l)
      : begin(loc.begin), first(f), last(l), end(loc.end),
        source(loc.source)
    {}
    region(location<Container>&& loc, const_iterator f, const_iterator l)
      : begin(loc.begin), first(f), last(l), end(loc.end),
        source(std::move(loc.source))
    {}

    region(const region&) = default;
    region(region&&)      = default;
    region& operator=(const region&) = default;
    region& operator=(region&&)      = default;
    ~region() = default;

    std::string str()  const {return std::string(first, last);}
    std::size_t size() const {return std::distance(first, last);}

    const_iterator begin, first, last, end;
    std::shared_ptr<const Container> source;
};

// to show a better error message.
template<typename Container>
std::string
format_underline(const region<Container>& reg, const std::string& msg)
{
    using const_iterator = typename region<Container>::const_iterator;
    using reverse_iterator = std::reverse_iterator<const_iterator>;
    const auto line_begin = std::find(
            reverse_iterator(reg.first),
            reverse_iterator(reg.begin),
            '\n').base();
    const auto line_end = std::find(reg.last, reg.end, '\n');

    const auto line_number = std::to_string(
            1 + std::count(reg.begin, reg.first, '\n'));

    std::string retval;
    retval += ' ';
    retval += line_number;
    retval += " | ";
    retval += std::string(line_begin, line_end);
    retval += '\n';
    retval += std::string(line_number.size() + 1, ' ');
    retval += " | ";
    retval += std::string(std::distance(line_begin, reg.first), ' ');
    retval += std::string(std::distance(reg.first, reg.last), '~');
    retval += ' ';
    retval += msg;
    return retval;
}

// to show a better error message.
template<typename Container>
std::string format_underline(const region<Container>& reg,
                             typename Container::const_iterator pos,
                             const std::string& msg)
{
    using const_iterator = typename region<Container>::const_iterator;
    using reverse_iterator = std::reverse_iterator<const_iterator>;
    const auto line_begin = std::find(
            reverse_iterator(reg.first),
            reverse_iterator(reg.begin),
            '\n').base();
    const auto line_end = std::find(reg.last, reg.end, '\n');

    const auto line_number = std::to_string(
            1 + std::count(reg.begin, reg.first, '\n'));

    std::string retval;
    retval += ' ';
    retval += line_number;
    retval += " | ";
    retval += std::string(line_begin, line_end);
    retval += '\n';
    retval += std::string(line_number.size() + 1, ' ');
    retval += " | ";
    retval += std::string(std::distance(line_begin, reg.first), ' ');

    if(std::distance(reg.first, std::prev(pos)) > 0)
    {
        retval += std::string(std::distance(reg.first, std::prev(pos)), '-');
    }
    retval += '^';
    if(std::distance(pos, reg.last) > 0)
    {
        retval += std::string(std::distance(std::next(pos), reg.last), '-');
    }

    retval += ' ';
    retval += msg;
    return retval;
}

} // detail
} // toml
#endif// TOML11_REGION_H
<commit_msg>make variables in region/location read-only<commit_after>#ifndef TOML11_REGION_H
#define TOML11_REGION_H
#include "exception.hpp"
#include <memory>
#include <algorithm>
#include <iterator>

namespace toml
{
namespace detail
{

// location in a container, normally in a file content.
// shared_ptr points the resource that the iter points.
// it can be used not only for resource handling, but also error message.
template<typename Container>
struct location
{
    static_assert(std::is_same<char, typename Container::value_type>::value,"");
    using const_iterator = typename Container::const_iterator;
    using source_ptr     = std::shared_ptr<const Container>;

    location(Container cont)
      : source_(std::make_shared<Container>(std::move(cont))),
        begin_(source_->cbegin()), iter_(source_->cbegin()),
        end_(source_->cend())
    {}
    location(const location&) = default;
    location(location&&)      = default;
    location& operator=(const location&) = default;
    location& operator=(location&&)      = default;
    ~location() = default;

    const_iterator& iter()       noexcept {return iter_;}
    const_iterator  iter() const noexcept {return iter_;}

    const_iterator  begin() const noexcept {return begin_;}
    const_iterator  end()   const noexcept {return end_;}

    source_ptr const& source() const& noexcept {return source_;}
    source_ptr&&      source() &&     noexcept {return std::move(source_);}

  private:

    source_ptr source_;
    const_iterator begin_, iter_, end_;
};

// region in a container, normally in a file content.
// shared_ptr points the resource that the iter points.
// combinators returns this.
// it can be used not only for resource handling, but also error message.
template<typename Container>
struct region
{
    static_assert(std::is_same<char, typename Container::value_type>::value,"");
    using const_iterator = typename Container::const_iterator;
    using source_ptr     = std::shared_ptr<const Container>;

    region(const location<Container>& loc)
      : begin_(loc.begin()), first_(loc.iter()),
        last_(loc.iter()), end_(loc.end()), source_(loc.source())
    {}
    region(location<Container>&& loc)
      : begin_(loc.begin()), first_(loc.iter()),
        last_(loc.iter()), end_(loc.end()), source_(std::move(loc.source()))
    {}

    region(const location<Container>& loc, const_iterator f, const_iterator l)
      : begin_(loc.begin()), first_(f), last_(l), end_(loc.end()),
        source_(loc.source())
    {}
    region(location<Container>&& loc, const_iterator f, const_iterator l)
      : begin_(loc.begin()), first_(f), last_(l), end_(loc.end()),
        source_(std::move(loc.source()))
    {}

    region(const region&) = default;
    region(region&&)      = default;
    region& operator=(const region&) = default;
    region& operator=(region&&)      = default;
    ~region() = default;

    region& operator+=(const region& other)
    {
        if(this->begin_ != other.begin_ || this->end_ != other.end_ ||
           this->last_  != other.first_)
        {
            throw internal_error("invalid region concatenation");
        }
        this->last_ = other.last_;
        return *this;
    }

    std::string str()  const {return std::string(first_, last_);}
    std::size_t size() const {return std::distance(first_, last_);}

    const_iterator  begin() const noexcept {return begin_;}
    const_iterator  end()   const noexcept {return end_;}
    const_iterator  first() const noexcept {return first_;}
    const_iterator  last()  const noexcept {return last_;}

    source_ptr const& source() const& noexcept {return source_;}
    source_ptr&&      source() &&     noexcept {return std::move(source_);}

  private:

    const_iterator begin_, first_, last_, end_;
    source_ptr source_;
};

// to show a better error message.
template<typename Container>
std::string
format_underline(const region<Container>& reg, const std::string& msg)
{
    using const_iterator = typename region<Container>::const_iterator;
    using reverse_iterator = std::reverse_iterator<const_iterator>;
    const auto line_begin = std::find(
            reverse_iterator(reg.first()),
            reverse_iterator(reg.begin()),
            '\n').base();
    const auto line_end = std::find(reg.last(), reg.end(), '\n');

    const auto line_number = std::to_string(
            1 + std::count(reg.begin(), reg.first(), '\n'));

    std::string retval;
    retval += ' ';
    retval += line_number;
    retval += " | ";
    retval += std::string(line_begin, line_end);
    retval += '\n';
    retval += std::string(line_number.size() + 1, ' ');
    retval += " | ";
    retval += std::string(std::distance(line_begin, reg.first()), ' ');
    retval += std::string(std::distance(reg.first(), reg.last()), '~');
    retval += ' ';
    retval += msg;
    return retval;
}

// to show a better error message.
template<typename Container>
std::string format_underline(const region<Container>& reg,
                             typename Container::const_iterator pos,
                             const std::string& msg)
{
    using const_iterator = typename region<Container>::const_iterator;
    using reverse_iterator = std::reverse_iterator<const_iterator>;
    const auto line_begin = std::find(
            reverse_iterator(reg.first()),
            reverse_iterator(reg.begin()),
            '\n').base();
    const auto line_end = std::find(reg.last(), reg.end(), '\n');

    const auto line_number = std::to_string(
            1 + std::count(reg.begin(), reg.first(), '\n'));

    std::string retval;
    retval += ' ';
    retval += line_number;
    retval += " | ";
    retval += std::string(line_begin, line_end);
    retval += '\n';
    retval += std::string(line_number.size() + 1, ' ');
    retval += " | ";
    retval += std::string(std::distance(line_begin, reg.first()), ' ');

    if(std::distance(reg.first(), std::prev(pos)) > 0)
    {
        retval += std::string(std::distance(reg.first(), std::prev(pos)), '-');
    }
    retval += '^';
    if(std::distance(pos, reg.last()) > 0)
    {
        retval += std::string(std::distance(std::next(pos), reg.last()), '-');
    }

    retval += ' ';
    retval += msg;
    return retval;
}

} // detail
} // toml
#endif// TOML11_REGION_H
<|endoftext|>


<commit_before>//     Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_TRAITS_HPP
#define TOML11_TRAITS_HPP
#include <type_traits>
#include <utility>
#include <chrono>
#include <tuple>
#include <string>
#if __cplusplus >= 201703L
#if __has_include(<string_view>)
#include <string_view>
#endif // has_include(<string_view>)
#endif // cplusplus   >= C++17

namespace toml
{

class value; // forward decl

namespace detail
{

template<typename T>
using unwrap_t = typename std::decay<T>::type;

// ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class

struct has_iterator_impl
{
    template<typename T> static std::true_type  check(typename T::iterator*);
    template<typename T> static std::false_type check(...);
};
struct has_value_type_impl
{
    template<typename T> static std::true_type  check(typename T::value_type*);
    template<typename T> static std::false_type check(...);
};
struct has_key_type_impl
{
    template<typename T> static std::true_type  check(typename T::key_type*);
    template<typename T> static std::false_type check(...);
};
struct has_mapped_type_impl
{
    template<typename T> static std::true_type  check(typename T::mapped_type*);
    template<typename T> static std::false_type check(...);
};
struct has_resize_method_impl
{
    constexpr static std::size_t dummy=0;
    template<typename T> static std::true_type  check(decltype(std::declval<T>().resize(dummy))*);
    template<typename T> static std::false_type check(...);
};

struct has_from_toml_method_impl
{
    template<typename T>
    static std::true_type  check(
        decltype(std::declval<T>().from_toml(std::declval<::toml::value>()))*);
    template<typename T>
    static std::false_type check(...);
};
struct has_into_toml_method_impl
{
    template<typename T>
    static std::true_type  check(decltype(std::declval<T>().into_toml())*);
    template<typename T>
    static std::false_type check(...);
};

/// Intel C++ compiler can not use decltype in parent class declaration, here
/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
#ifdef __INTEL_COMPILER
#define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type
#endif

template<typename T>
struct has_iterator    : decltype(has_iterator_impl::check<T>(nullptr)){};
template<typename T>
struct has_value_type  : decltype(has_value_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_key_type    : decltype(has_key_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};

template<typename T>
struct has_from_toml_method
: decltype(has_from_toml_method_impl::check<T>(nullptr)){};
template<typename T>
struct has_into_toml_method
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};

#ifdef __INTEL_COMPILER
#undef decltype(...)
#endif

// ---------------------------------------------------------------------------
// C++17 and/or/not

template<typename ...> struct conjunction : std::true_type{};
template<typename T>   struct conjunction<T> : T{};
template<typename T, typename ... Ts>
struct conjunction<T, Ts...> :
    std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
{};

template<typename ...> struct disjunction : std::false_type{};
template<typename T>   struct disjunction<T> : T {};
template<typename T, typename ... Ts>
struct disjunction<T, Ts...> :
    std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
{};

template<typename T>
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};

// ---------------------------------------------------------------------------
// type checkers

template<typename T> struct is_std_pair : std::false_type{};
template<typename T1, typename T2>
struct is_std_pair<std::pair<T1, T2>> : std::true_type{};

template<typename T> struct is_std_tuple : std::false_type{};
template<typename ... Ts>
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};

template<typename T> struct is_chrono_duration: std::false_type{};
template<typename Rep, typename Period>
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};

template<typename T>
struct is_map : conjunction< // map satisfies all the following conditions
    has_iterator<T>,         // has T::iterator
    has_value_type<T>,       // has T::value_type
    has_key_type<T>,         // has T::key_type
    has_mapped_type<T>       // has T::mapped_type
    >{};
template<typename T> struct is_map<T&>                : is_map<T>{};
template<typename T> struct is_map<T const&>          : is_map<T>{};
template<typename T> struct is_map<T volatile&>       : is_map<T>{};
template<typename T> struct is_map<T const volatile&> : is_map<T>{};

template<typename T>
struct is_container : conjunction<
    negation<is_map<T>>,                         // not a map
    negation<std::is_same<T, std::string>>,      // not a std::string
#if __cplusplus >= 201703L
    negation<std::is_same<T, std::string_view>>, // not a std::string_view
#endif
    has_iterator<T>,                             // has T::iterator
    has_value_type<T>                            // has T::value_type
    >{};
template<typename T> struct is_container<T&>                : is_container<T>{};
template<typename T> struct is_container<T const&>          : is_container<T>{};
template<typename T> struct is_container<T volatile&>       : is_container<T>{};
template<typename T> struct is_container<T const volatile&> : is_container<T>{};

// ---------------------------------------------------------------------------
// C++14 index_sequence

template<std::size_t ... Ns> struct index_sequence{};

template<typename IS, std::size_t N> struct push_back_index_sequence{};
template<std::size_t N, std::size_t ... Ns>
struct push_back_index_sequence<index_sequence<Ns...>, N>
{
    typedef index_sequence<Ns..., N> type;
};

template<std::size_t N>
struct index_sequence_maker
{
    typedef typename push_back_index_sequence<
        typename index_sequence_maker<N-1>::type, N>::type type;
};
template<>
struct index_sequence_maker<0>
{
    typedef index_sequence<0> type;
};
template<std::size_t N>
using make_index_sequence = typename index_sequence_maker<N-1>::type;

// ---------------------------------------------------------------------------
// return_type_of_t

#if __cplusplus >= 201703L

template<typename F, typename ... Args>
using return_type_of_t = std::invoke_result_t<F, Args...>;

#else
// result_of is deprecated after C++17
template<typename F, typename ... Args>
using return_type_of_t = typename std::result_of<F(Args...)>::type;

#endif

// ---------------------------------------------------------------------------
// is_string_literal
//
// to use this, pass `typename remove_reference<T>::type` to T.

template<typename T>
struct is_string_literal:
disjunction<
    std::is_same<const char*, T>,
    conjunction<
        std::is_array<T>,
        std::is_same<const char, typename std::remove_extent<T>::type>
        >
    >{};

}// detail
}//toml
#endif // TOML_TRAITS
<commit_msg>fix: fix has_from_toml using basic_value<commit_after>//     Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_TRAITS_HPP
#define TOML11_TRAITS_HPP
#include <type_traits>
#include <utility>
#include <chrono>
#include <tuple>
#include <string>
#if __cplusplus >= 201703L
#if __has_include(<string_view>)
#include <string_view>
#endif // has_include(<string_view>)
#endif // cplusplus   >= C++17

#include "comments.hpp"
#include <vector>
#include <unordered_map>

namespace toml
{
template<typename C, template<typename ...> class T, template<typename ...> class A>
class basic_value;

namespace detail
{

template<typename T>
using unwrap_t = typename std::decay<T>::type;

// ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class

struct has_iterator_impl
{
    template<typename T> static std::true_type  check(typename T::iterator*);
    template<typename T> static std::false_type check(...);
};
struct has_value_type_impl
{
    template<typename T> static std::true_type  check(typename T::value_type*);
    template<typename T> static std::false_type check(...);
};
struct has_key_type_impl
{
    template<typename T> static std::true_type  check(typename T::key_type*);
    template<typename T> static std::false_type check(...);
};
struct has_mapped_type_impl
{
    template<typename T> static std::true_type  check(typename T::mapped_type*);
    template<typename T> static std::false_type check(...);
};
struct has_resize_method_impl
{
    constexpr static std::size_t dummy=0;
    template<typename T> static std::true_type  check(decltype(std::declval<T>().resize(dummy))*);
    template<typename T> static std::false_type check(...);
};

struct has_from_toml_method_impl
{
    template<typename T>
    static std::true_type  check(
        decltype(std::declval<T>().from_toml(std::declval<::toml::basic_value<
                ::toml::discard_comments, std::unordered_map, std::vector>>()
                )
        )*);
    template<typename T>
    static std::false_type check(...);
};
struct has_into_toml_method_impl
{
    template<typename T>
    static std::true_type  check(decltype(std::declval<T>().into_toml())*);
    template<typename T>
    static std::false_type check(...);
};

/// Intel C++ compiler can not use decltype in parent class declaration, here
/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
#ifdef __INTEL_COMPILER
#define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type
#endif

template<typename T>
struct has_iterator    : decltype(has_iterator_impl::check<T>(nullptr)){};
template<typename T>
struct has_value_type  : decltype(has_value_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_key_type    : decltype(has_key_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};

template<typename T>
struct has_from_toml_method
: decltype(has_from_toml_method_impl::check<T>(nullptr)){};
template<typename T>
struct has_into_toml_method
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};

#ifdef __INTEL_COMPILER
#undef decltype(...)
#endif

// ---------------------------------------------------------------------------
// C++17 and/or/not

template<typename ...> struct conjunction : std::true_type{};
template<typename T>   struct conjunction<T> : T{};
template<typename T, typename ... Ts>
struct conjunction<T, Ts...> :
    std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
{};

template<typename ...> struct disjunction : std::false_type{};
template<typename T>   struct disjunction<T> : T {};
template<typename T, typename ... Ts>
struct disjunction<T, Ts...> :
    std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
{};

template<typename T>
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};

// ---------------------------------------------------------------------------
// type checkers

template<typename T> struct is_std_pair : std::false_type{};
template<typename T1, typename T2>
struct is_std_pair<std::pair<T1, T2>> : std::true_type{};

template<typename T> struct is_std_tuple : std::false_type{};
template<typename ... Ts>
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};

template<typename T> struct is_chrono_duration: std::false_type{};
template<typename Rep, typename Period>
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};

template<typename T>
struct is_map : conjunction< // map satisfies all the following conditions
    has_iterator<T>,         // has T::iterator
    has_value_type<T>,       // has T::value_type
    has_key_type<T>,         // has T::key_type
    has_mapped_type<T>       // has T::mapped_type
    >{};
template<typename T> struct is_map<T&>                : is_map<T>{};
template<typename T> struct is_map<T const&>          : is_map<T>{};
template<typename T> struct is_map<T volatile&>       : is_map<T>{};
template<typename T> struct is_map<T const volatile&> : is_map<T>{};

template<typename T>
struct is_container : conjunction<
    negation<is_map<T>>,                         // not a map
    negation<std::is_same<T, std::string>>,      // not a std::string
#if __cplusplus >= 201703L
    negation<std::is_same<T, std::string_view>>, // not a std::string_view
#endif
    has_iterator<T>,                             // has T::iterator
    has_value_type<T>                            // has T::value_type
    >{};
template<typename T> struct is_container<T&>                : is_container<T>{};
template<typename T> struct is_container<T const&>          : is_container<T>{};
template<typename T> struct is_container<T volatile&>       : is_container<T>{};
template<typename T> struct is_container<T const volatile&> : is_container<T>{};

// ---------------------------------------------------------------------------
// C++14 index_sequence

template<std::size_t ... Ns> struct index_sequence{};

template<typename IS, std::size_t N> struct push_back_index_sequence{};
template<std::size_t N, std::size_t ... Ns>
struct push_back_index_sequence<index_sequence<Ns...>, N>
{
    typedef index_sequence<Ns..., N> type;
};

template<std::size_t N>
struct index_sequence_maker
{
    typedef typename push_back_index_sequence<
        typename index_sequence_maker<N-1>::type, N>::type type;
};
template<>
struct index_sequence_maker<0>
{
    typedef index_sequence<0> type;
};
template<std::size_t N>
using make_index_sequence = typename index_sequence_maker<N-1>::type;

// ---------------------------------------------------------------------------
// return_type_of_t

#if __cplusplus >= 201703L

template<typename F, typename ... Args>
using return_type_of_t = std::invoke_result_t<F, Args...>;

#else
// result_of is deprecated after C++17
template<typename F, typename ... Args>
using return_type_of_t = typename std::result_of<F(Args...)>::type;

#endif

// ---------------------------------------------------------------------------
// is_string_literal
//
// to use this, pass `typename remove_reference<T>::type` to T.

template<typename T>
struct is_string_literal:
disjunction<
    std::is_same<const char*, T>,
    conjunction<
        std::is_array<T>,
        std::is_same<const char, typename std::remove_extent<T>::type>
        >
    >{};

}// detail
}//toml
#endif // TOML_TRAITS
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: simplecontinuousactivitybase.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-21 17:00:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX
#define _SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX

#include <activitybase.hxx>
#include <canvas/elapsedtime.hxx>

namespace presentation
{
    namespace internal
    {
        /** Simple, continuous animation.

            This class implements a simple, continuous animation
            without considering repeats or acceleration on the
            perform call. Only useful as a base class, you
            probably want to use ContinuousActivityBase.
        */
        class SimpleContinuousActivityBase : public ActivityBase
        {
        public:
            SimpleContinuousActivityBase( const ActivityParameters& rParms );

            /** Hook for derived classes

                This method will be called from perform().

                @param nSimpleTime
                Simple animation time, without repeat,
                acceleration or deceleration applied. This value
                is always in the [0,1] range, the repeat is
                accounted for with the nRepeatCount parameter.

                @param nRepeatCount
                Number of full repeats already performed
            */
            virtual void simplePerform( double nSimpleTime, sal_uInt32 nRepeatCount ) const = 0;

            virtual void start();

            virtual bool perform();

        protected:
            /// Time elapsed since activity started
            ::canvas::tools::ElapsedTime    maTimer;

            /// Simple duration of activity
            const double                    mnMinSimpleDuration;

            /// Minimal number of frames to show (see ActivityParameters)
            const sal_uInt32                mnMinNumberOfFrames;

            /// Actual number of frames shown until now.
            sal_uInt32                      mnCurrPerformCalls;
        };
    }
}

#endif /* _SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX */
<commit_msg>INTEGRATION: CWS presfixes01 (1.2.2); FILE MERGED 2005/02/17 23:56:53 thb 1.2.2.4: #i42499# Made de-spriting of shape effects happen in new Activity::dequeued() method; removed Activity::end() method; fixed calculation of XSlideShow::update() wait interval; slightly modified pres time handling, pres time is now held during _all_ queue processing, including EventQueue (generated funny bounce and break effects, because delayed activities got out of sync); clarified documentation 2005/02/02 22:47:00 dbo 1.2.2.3: #i37777# - timing changes for activities queue - minor fixes Issue number: Submitted by: Reviewed by: 2005/01/30 16:00:58 dbo 1.2.2.2: #i37777# - using single presentation time base - activities queue detects and sets timing lag (calcTimeLag()) Issue number: Submitted by: Reviewed by: 2005/01/27 15:58:18 dbo 1.2.2.1: #i39662# using shared timer for correct pausing Issue number: Submitted by: Reviewed by:<commit_after>/*************************************************************************
 *
 *  $RCSfile: simplecontinuousactivitybase.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 13:49:20 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX
#define _SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX

#include <activitybase.hxx>
#include <canvas/elapsedtime.hxx>

namespace presentation
{
    namespace internal
    {
        /** Simple, continuous animation.

            This class implements a simple, continuous animation
            without considering repeats or acceleration on the
            perform call. Only useful as a base class, you
            probably want to use ContinuousActivityBase.
        */
        class SimpleContinuousActivityBase : public ActivityBase
        {
        public:
            SimpleContinuousActivityBase( const ActivityParameters& rParms );

            virtual double calcTimeLag() const;

            virtual bool perform();
            virtual void dequeued();

        protected:
            /** Hook for derived classes

                This method will be called from perform().

                @param nSimpleTime
                Simple animation time, without repeat,
                acceleration or deceleration applied. This value
                is always in the [0,1] range, the repeat is
                accounted for with the nRepeatCount parameter.

                @param nRepeatCount
                Number of full repeats already performed
            */
            virtual void simplePerform( double nSimpleTime, sal_uInt32 nRepeatCount ) const = 0;

            virtual void startAnimation();

        private:
            /// Time elapsed since activity started
            ::canvas::tools::ElapsedTime    maTimer;

            /// Simple duration of activity
            const double                    mnMinSimpleDuration;

            /// Minimal number of frames to show (see ActivityParameters)
            const sal_uInt32                mnMinNumberOfFrames;

            /// Actual number of frames shown until now.
            sal_uInt32                      mnCurrPerformCalls;
        };
    }
}

#endif /* _SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX */
<|endoftext|>


<commit_before>#include <gloperate-qtwidgets/ImageExporterResolutionWidget.h>

#include <gloperate-qt/qt-includes-begin.h>
#include "ui_ImageExporterResolutionWidget.h"
#include <gloperate-qt/qt-includes-end.h>

#define CM_PER_INCH 2.54
#define INCH_PER_CM 1 / CM_PER_INCH

namespace gloperate_qtwidgets
{

const QString ppiString = "ppi";
const QString pixelsPerCmString = "px/cm";
const QString pixelString = "pixel";
const QString inchString = "inch";
const QString cmString = "cm";

ImageExporterResolutionWidget::ImageExporterResolutionWidget(QWidget *parent)
:	QWidget(parent)
,	m_widthState(new ResolutionState(1920.0, pixelString))
,	m_heightState(new ResolutionState(1080.0, pixelString))
,	m_resolutionState(new ResolutionState(72, ppiString))
,	m_ui(new Ui_ImageExporterResolutionWidget)
{
    m_ui->setupUi(this);

    void (QComboBox:: *comboBoxCurrentIndexChanged)(const QString &) = &QComboBox::currentIndexChanged;
    connect(m_ui->widthComboBox, comboBoxCurrentIndexChanged,
        this, &ImageExporterResolutionWidget::widthUnitChanged);
    connect(m_ui->heightComboBox, comboBoxCurrentIndexChanged,
        this, &ImageExporterResolutionWidget::heightUnitChanged);
    connect(m_ui->resolutionComboBox, comboBoxCurrentIndexChanged,
        this, &ImageExporterResolutionWidget::resolutionUnitChanged);

    void (QDoubleSpinBox:: *doubleSpinBoxValueChanged)(double d) = &QDoubleSpinBox::valueChanged;
    void (QSpinBox:: *spinBoxValueChanged)(int i) = &QSpinBox::valueChanged;
    connect(m_ui->widthDoubleSpinBox, doubleSpinBoxValueChanged,
        this, &ImageExporterResolutionWidget::widthValueChanged);
    connect(m_ui->heightDoubleSpinBox, doubleSpinBoxValueChanged,
        this, &ImageExporterResolutionWidget::heightValueChanged);
    connect(m_ui->resolutionSpinBox, spinBoxValueChanged,
        this, &ImageExporterResolutionWidget::resolutionValueChanged);

    m_ui->widthDoubleSpinBox->setRange(0.01, 100000.0);
    m_ui->heightDoubleSpinBox->setRange(0.01, 100000.0);

    QStringList units{ pixelString, inchString, cmString };
    m_ui->widthComboBox->addItems(units);
    m_ui->heightComboBox->addItems(units);

    QStringList resolutions{ ppiString, pixelsPerCmString };
    bool oldComboBoxSignalStatus = m_ui->resolutionComboBox->blockSignals(true);
    m_ui->resolutionComboBox->addItems(resolutions);
    m_ui->resolutionComboBox->blockSignals(oldComboBoxSignalStatus);

    bool oldSpinBoxSignalStatus = m_ui->resolutionSpinBox->blockSignals(true);
    m_ui->resolutionSpinBox->setValue(72);
    m_ui->resolutionSpinBox->blockSignals(oldSpinBoxSignalStatus);
}

void ImageExporterResolutionWidget::updateResolutionSummary()
{
    // TODO: detect unsigned long long overflow
    int height{ static_cast<int>(std::round(toPixels(m_heightState->value, m_heightState->type))) };
    int width{ static_cast<int>(std::round(toPixels(m_widthState->value, m_widthState->type))) };
    emit resolutionChanged(QSize(width, height));

    unsigned long long pixelNumber{ static_cast<unsigned long long>(width) * static_cast<unsigned long long>(height) };
    QString unit;
    double byte;
    if (pixelNumber * 4 < 1024)
    {
        unit = "Byte";
        byte = static_cast<double>(pixelNumber) * 4;
    }
    else if (pixelNumber * 4 < static_cast<unsigned long long>(pow<unsigned long long>(1024, 2)))
    {
        unit = "KiB";
        byte = static_cast<double>(pixelNumber) * 4 / 1024;
    }
    else if (pixelNumber * 4 < static_cast<unsigned long long>(pow<unsigned long long>(1024, 3)))
    {
        unit = "MiB";
        byte = static_cast<double>(pixelNumber) * 4 / pow<unsigned long long>(1024, 2);
    }
    else if (pixelNumber * 4 < static_cast<unsigned long long>(pow<unsigned long long>(1024, 4)))
    {
        unit = "GiB";
        byte = static_cast<double>(pixelNumber) * 4 / pow<unsigned long long>(1024, 3);
    }
    else //if (pixelNumber * 4 < static_cast<unsigned long long>(pow<unsigned long long>(1024, 5)))
    {
        unit = "TiB";
        byte = static_cast<double>(pixelNumber) * 4 / pow<unsigned long long>(1024, 4);
    }
    QString summary{ QString::number(pixelNumber) + " pixels (" + QString::number(std::round(byte * 100) / 100) + " " + unit + " uncompressed)" };
    //m_ui->resolutionSummaryLabel->setText(summary);
    emit resolutionSummaryChanged(summary);
}

double ImageExporterResolutionWidget::inchToPixels(double value)
{
    if (m_resolutionState->type == ppiString)
        value *= m_resolutionState->value;
    else if (m_resolutionState->type == pixelsPerCmString)
        value *= m_resolutionState->value * CM_PER_INCH;

    return value;
}

double ImageExporterResolutionWidget::cmToPixels(double value)
{
    if (m_resolutionState->type == ppiString)
        value *= m_resolutionState->value * INCH_PER_CM;
    else if (m_resolutionState->type == pixelsPerCmString)
        value *= m_resolutionState->value;

    return value;
}

double ImageExporterResolutionWidget::toPixels(double value, const QString& type)
{
    if (type == inchString)
        value = inchToPixels(value);
    else if (type == cmString)
        value = cmToPixels(value);

    return value;
}

double ImageExporterResolutionWidget::pixelsToCm(double value)
{
    if (m_resolutionState->type == ppiString)
        value *= CM_PER_INCH / m_resolutionState->value;
    else if (m_resolutionState->type == pixelsPerCmString)
        value /= m_resolutionState->value;

    return value;
}

double ImageExporterResolutionWidget::pixelsToInch(double value)
{
    if (m_resolutionState->type == ppiString)
        value /= m_resolutionState->value;
    else if (m_resolutionState->type == pixelsPerCmString)
        value *= INCH_PER_CM / m_resolutionState->value;

    return value;
}

double ImageExporterResolutionWidget::pixelsTo(double value, const QString& type)
{
    if (type == inchString)
        value = pixelsToInch(value);
    else if (type == cmString)
        value = pixelsToCm(value);

    return value;
}

void ImageExporterResolutionWidget::setDecimals(QDoubleSpinBox* box, int dec)
{
    bool old = box->blockSignals(true);
    box->setDecimals(dec);
    box->blockSignals(old);
}

void ImageExporterResolutionWidget::widthUnitChanged(const QString& text)
{
    if (text == pixelString)
    {
        m_widthState->value = toPixels(m_widthState->value, m_widthState->type);

        if (m_ui->heightComboBox->currentText() == pixelString)
            enableResolution(false);

        setDecimals(m_ui->widthDoubleSpinBox, 0);
    }
    else if (text == inchString)
    {
        if (m_widthState->type == pixelString)
        {
            m_widthState->value = pixelsToInch(m_widthState->value);

            setDecimals(m_ui->widthDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_widthState->type == cmString)
            m_widthState->value = m_widthState->value * INCH_PER_CM;
    }
    else
    {
        if (m_widthState->type == pixelString)
        {
            m_widthState->value = pixelsToCm(m_widthState->value);

            setDecimals(m_ui->widthDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_widthState->type == inchString)
            m_widthState->value = m_widthState->value * CM_PER_INCH;
    }

    m_ui->widthDoubleSpinBox->setValue(m_widthState->value);
    m_widthState->type = text;
}

void ImageExporterResolutionWidget::heightUnitChanged(const QString& text)
{
    if (text == pixelString)
    {
        m_heightState->value = toPixels(m_heightState->value, m_heightState->type);

        if (m_ui->widthComboBox->currentText() == pixelString)
            enableResolution(false);

        setDecimals(m_ui->heightDoubleSpinBox, 0);
    }
    else if (text == inchString)
    {
        if (m_heightState->type == pixelString)
        {
            m_heightState->value = pixelsToInch(m_heightState->value);

            setDecimals(m_ui->heightDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_heightState->type == cmString)
            m_heightState->value = m_heightState->value * INCH_PER_CM;
    }
    else
    {
        if (m_heightState->type == pixelString)
        {
            m_heightState->value = pixelsToCm(m_heightState->value);

            setDecimals(m_ui->heightDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_heightState->type == inchString)
            m_heightState->value = m_heightState->value * CM_PER_INCH;
    }

    m_ui->heightDoubleSpinBox->setValue(m_heightState->value);
    m_heightState->type = text;
}

void ImageExporterResolutionWidget::widthValueChanged(double d)
{
    if (m_ui->aspectCheckBox->isChecked())
    {
        double newValue{ toPixels(d, m_widthState->type) * toPixels(m_heightState->value, m_heightState->type) / toPixels(m_widthState->value, m_widthState->type) };
        m_heightState->value = pixelsTo(newValue, m_heightState->type);

        bool old = m_ui->heightDoubleSpinBox->blockSignals(true);
        if (m_heightState->type == pixelString)
            m_ui->heightDoubleSpinBox->setValue(std::round(m_heightState->value));
        else
            m_ui->heightDoubleSpinBox->setValue(m_heightState->value);
        m_ui->heightDoubleSpinBox->blockSignals(old);
    }

    m_widthState->value = d;

    updateResolutionSummary();
}

void ImageExporterResolutionWidget::heightValueChanged(double d)
{
    if (m_ui->aspectCheckBox->isChecked())
    {
        double newValue{ toPixels(d, m_heightState->type) * toPixels(m_widthState->value, m_widthState->type) / toPixels(m_heightState->value, m_heightState->type) };
        m_widthState->value = pixelsTo(newValue, m_widthState->type);

        bool old = m_ui->widthDoubleSpinBox->blockSignals(true);
        if (m_widthState->type == pixelString)
            m_ui->widthDoubleSpinBox->setValue(std::round(m_widthState->value));
        else
            m_ui->widthDoubleSpinBox->setValue(m_widthState->value);
        m_ui->widthDoubleSpinBox->blockSignals(old);
    }

    m_heightState->value = d;

    updateResolutionSummary();
}

void ImageExporterResolutionWidget::resolutionValueChanged(int i)
{
    double value;
    bool old;
    if (m_ui->aspectCheckBox->isChecked())
    {
        if (m_widthState->type == pixelString)
        {
            value = pixelsTo(m_widthState->value, m_heightState->type);
            m_resolutionState->value = i;
            m_widthState->value = toPixels(value, m_heightState->type);

            old = m_ui->widthDoubleSpinBox->blockSignals(true);
            m_ui->widthDoubleSpinBox->setValue(std::round(m_widthState->value));
            m_ui->widthDoubleSpinBox->blockSignals(old);
        }
        else if (m_heightState->type == pixelString)
        {
            value = pixelsTo(m_heightState->value, m_widthState->type);
            m_resolutionState->value = i;
            m_heightState->value = toPixels(value, m_widthState->type);

            old = m_ui->heightDoubleSpinBox->blockSignals(true);
            m_ui->heightDoubleSpinBox->setValue(std::round(m_heightState->value));
            m_ui->heightDoubleSpinBox->blockSignals(old);
        }
    }
    else
        m_resolutionState->value = i;

    updateResolutionSummary();
}

void ImageExporterResolutionWidget::resolutionUnitChanged(const QString& text)
{
    if (text == ppiString)
        m_resolutionState->value = std::ceil(m_resolutionState->value * CM_PER_INCH);
    else
        m_resolutionState->value = std::ceil(m_resolutionState->value * INCH_PER_CM);

    m_ui->resolutionSpinBox->setValue(m_resolutionState->value);
    m_resolutionState->type = text;
}

void ImageExporterResolutionWidget::enableResolution(bool enable)
{
    m_ui->resolutionSpinBox->setEnabled(enable);
    m_ui->resolutionComboBox->setEnabled(enable);
    m_ui->resolutionLabel->setEnabled(enable);
}

ImageExporterResolutionWidget::~ImageExporterResolutionWidget()
{
}

} //namespace gloperate_qtwidgets
<commit_msg>Try to fix  error: expected ‘)’ before ‘unsigned’ in ImageExporterResolutionWidget<commit_after>#include <gloperate-qtwidgets/ImageExporterResolutionWidget.h>

#include <gloperate-qt/qt-includes-begin.h>
#include "ui_ImageExporterResolutionWidget.h"
#include <gloperate-qt/qt-includes-end.h>

#define CM_PER_INCH 2.54
#define INCH_PER_CM 1 / CM_PER_INCH

namespace gloperate_qtwidgets
{

const QString ppiString = "ppi";
const QString pixelsPerCmString = "px/cm";
const QString pixelString = "pixel";
const QString inchString = "inch";
const QString cmString = "cm";

ImageExporterResolutionWidget::ImageExporterResolutionWidget(QWidget *parent)
:	QWidget(parent)
,	m_widthState(new ResolutionState(1920.0, pixelString))
,	m_heightState(new ResolutionState(1080.0, pixelString))
,	m_resolutionState(new ResolutionState(72, ppiString))
,	m_ui(new Ui_ImageExporterResolutionWidget)
{
    m_ui->setupUi(this);

    void (QComboBox:: *comboBoxCurrentIndexChanged)(const QString &) = &QComboBox::currentIndexChanged;
    connect(m_ui->widthComboBox, comboBoxCurrentIndexChanged,
        this, &ImageExporterResolutionWidget::widthUnitChanged);
    connect(m_ui->heightComboBox, comboBoxCurrentIndexChanged,
        this, &ImageExporterResolutionWidget::heightUnitChanged);
    connect(m_ui->resolutionComboBox, comboBoxCurrentIndexChanged,
        this, &ImageExporterResolutionWidget::resolutionUnitChanged);

    void (QDoubleSpinBox:: *doubleSpinBoxValueChanged)(double d) = &QDoubleSpinBox::valueChanged;
    void (QSpinBox:: *spinBoxValueChanged)(int i) = &QSpinBox::valueChanged;
    connect(m_ui->widthDoubleSpinBox, doubleSpinBoxValueChanged,
        this, &ImageExporterResolutionWidget::widthValueChanged);
    connect(m_ui->heightDoubleSpinBox, doubleSpinBoxValueChanged,
        this, &ImageExporterResolutionWidget::heightValueChanged);
    connect(m_ui->resolutionSpinBox, spinBoxValueChanged,
        this, &ImageExporterResolutionWidget::resolutionValueChanged);

    m_ui->widthDoubleSpinBox->setRange(0.01, 100000.0);
    m_ui->heightDoubleSpinBox->setRange(0.01, 100000.0);

    QStringList units{ pixelString, inchString, cmString };
    m_ui->widthComboBox->addItems(units);
    m_ui->heightComboBox->addItems(units);

    QStringList resolutions{ ppiString, pixelsPerCmString };
    bool oldComboBoxSignalStatus = m_ui->resolutionComboBox->blockSignals(true);
    m_ui->resolutionComboBox->addItems(resolutions);
    m_ui->resolutionComboBox->blockSignals(oldComboBoxSignalStatus);

    bool oldSpinBoxSignalStatus = m_ui->resolutionSpinBox->blockSignals(true);
    m_ui->resolutionSpinBox->setValue(72);
    m_ui->resolutionSpinBox->blockSignals(oldSpinBoxSignalStatus);
}

void ImageExporterResolutionWidget::updateResolutionSummary()
{
    // TODO: detect unsigned long long overflow
    int height{ static_cast<int>(std::round(toPixels(m_heightState->value, m_heightState->type))) };
    int width{ static_cast<int>(std::round(toPixels(m_widthState->value, m_widthState->type))) };
    emit resolutionChanged(QSize(width, height));

    unsigned long long pixelNumber{ static_cast<unsigned long long>(width) * static_cast<unsigned long long>(height) };
    QString unit;
    double byte;
    if (pixelNumber * 4 < 1024)
    {
        unit = "Byte";
        byte = static_cast<double>(pixelNumber) * 4;
    }
    else if (pixelNumber * 4 < static_cast<unsigned long long>(pow<int>(1024, 2)))
    {
        unit = "KiB";
        byte = static_cast<double>(pixelNumber) * 4 / 1024;
    }
    else if (pixelNumber * 4 < static_cast<unsigned long long>(pow<int>(1024, 3)))
    {
        unit = "MiB";
        byte = static_cast<double>(pixelNumber) * 4 / pow<int>(1024, 2);
    }
    else if (pixelNumber * 4 < static_cast<unsigned long long>(pow<int>(1024, 4)))
    {
        unit = "GiB";
        byte = static_cast<double>(pixelNumber) * 4 / pow<int>(1024, 3);
    }
    else //if (pixelNumber * 4 < static_cast<unsigned long long>(pow<>(1024, 5)))
    {
        unit = "TiB";
        byte = static_cast<double>(pixelNumber) * 4 / pow<int>(1024, 4);
    }
    QString summary{ QString::number(pixelNumber) + " pixels (" + QString::number(std::round(byte * 100) / 100) + " " + unit + " uncompressed)" };
    //m_ui->resolutionSummaryLabel->setText(summary);
    emit resolutionSummaryChanged(summary);
}

double ImageExporterResolutionWidget::inchToPixels(double value)
{
    if (m_resolutionState->type == ppiString)
        value *= m_resolutionState->value;
    else if (m_resolutionState->type == pixelsPerCmString)
        value *= m_resolutionState->value * CM_PER_INCH;

    return value;
}

double ImageExporterResolutionWidget::cmToPixels(double value)
{
    if (m_resolutionState->type == ppiString)
        value *= m_resolutionState->value * INCH_PER_CM;
    else if (m_resolutionState->type == pixelsPerCmString)
        value *= m_resolutionState->value;

    return value;
}

double ImageExporterResolutionWidget::toPixels(double value, const QString& type)
{
    if (type == inchString)
        value = inchToPixels(value);
    else if (type == cmString)
        value = cmToPixels(value);

    return value;
}

double ImageExporterResolutionWidget::pixelsToCm(double value)
{
    if (m_resolutionState->type == ppiString)
        value *= CM_PER_INCH / m_resolutionState->value;
    else if (m_resolutionState->type == pixelsPerCmString)
        value /= m_resolutionState->value;

    return value;
}

double ImageExporterResolutionWidget::pixelsToInch(double value)
{
    if (m_resolutionState->type == ppiString)
        value /= m_resolutionState->value;
    else if (m_resolutionState->type == pixelsPerCmString)
        value *= INCH_PER_CM / m_resolutionState->value;

    return value;
}

double ImageExporterResolutionWidget::pixelsTo(double value, const QString& type)
{
    if (type == inchString)
        value = pixelsToInch(value);
    else if (type == cmString)
        value = pixelsToCm(value);

    return value;
}

void ImageExporterResolutionWidget::setDecimals(QDoubleSpinBox* box, int dec)
{
    bool old = box->blockSignals(true);
    box->setDecimals(dec);
    box->blockSignals(old);
}

void ImageExporterResolutionWidget::widthUnitChanged(const QString& text)
{
    if (text == pixelString)
    {
        m_widthState->value = toPixels(m_widthState->value, m_widthState->type);

        if (m_ui->heightComboBox->currentText() == pixelString)
            enableResolution(false);

        setDecimals(m_ui->widthDoubleSpinBox, 0);
    }
    else if (text == inchString)
    {
        if (m_widthState->type == pixelString)
        {
            m_widthState->value = pixelsToInch(m_widthState->value);

            setDecimals(m_ui->widthDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_widthState->type == cmString)
            m_widthState->value = m_widthState->value * INCH_PER_CM;
    }
    else
    {
        if (m_widthState->type == pixelString)
        {
            m_widthState->value = pixelsToCm(m_widthState->value);

            setDecimals(m_ui->widthDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_widthState->type == inchString)
            m_widthState->value = m_widthState->value * CM_PER_INCH;
    }

    m_ui->widthDoubleSpinBox->setValue(m_widthState->value);
    m_widthState->type = text;
}

void ImageExporterResolutionWidget::heightUnitChanged(const QString& text)
{
    if (text == pixelString)
    {
        m_heightState->value = toPixels(m_heightState->value, m_heightState->type);

        if (m_ui->widthComboBox->currentText() == pixelString)
            enableResolution(false);

        setDecimals(m_ui->heightDoubleSpinBox, 0);
    }
    else if (text == inchString)
    {
        if (m_heightState->type == pixelString)
        {
            m_heightState->value = pixelsToInch(m_heightState->value);

            setDecimals(m_ui->heightDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_heightState->type == cmString)
            m_heightState->value = m_heightState->value * INCH_PER_CM;
    }
    else
    {
        if (m_heightState->type == pixelString)
        {
            m_heightState->value = pixelsToCm(m_heightState->value);

            setDecimals(m_ui->heightDoubleSpinBox, 2);
            enableResolution(true);
        }
        else if (m_heightState->type == inchString)
            m_heightState->value = m_heightState->value * CM_PER_INCH;
    }

    m_ui->heightDoubleSpinBox->setValue(m_heightState->value);
    m_heightState->type = text;
}

void ImageExporterResolutionWidget::widthValueChanged(double d)
{
    if (m_ui->aspectCheckBox->isChecked())
    {
        double newValue{ toPixels(d, m_widthState->type) * toPixels(m_heightState->value, m_heightState->type) / toPixels(m_widthState->value, m_widthState->type) };
        m_heightState->value = pixelsTo(newValue, m_heightState->type);

        bool old = m_ui->heightDoubleSpinBox->blockSignals(true);
        if (m_heightState->type == pixelString)
            m_ui->heightDoubleSpinBox->setValue(std::round(m_heightState->value));
        else
            m_ui->heightDoubleSpinBox->setValue(m_heightState->value);
        m_ui->heightDoubleSpinBox->blockSignals(old);
    }

    m_widthState->value = d;

    updateResolutionSummary();
}

void ImageExporterResolutionWidget::heightValueChanged(double d)
{
    if (m_ui->aspectCheckBox->isChecked())
    {
        double newValue{ toPixels(d, m_heightState->type) * toPixels(m_widthState->value, m_widthState->type) / toPixels(m_heightState->value, m_heightState->type) };
        m_widthState->value = pixelsTo(newValue, m_widthState->type);

        bool old = m_ui->widthDoubleSpinBox->blockSignals(true);
        if (m_widthState->type == pixelString)
            m_ui->widthDoubleSpinBox->setValue(std::round(m_widthState->value));
        else
            m_ui->widthDoubleSpinBox->setValue(m_widthState->value);
        m_ui->widthDoubleSpinBox->blockSignals(old);
    }

    m_heightState->value = d;

    updateResolutionSummary();
}

void ImageExporterResolutionWidget::resolutionValueChanged(int i)
{
    double value;
    bool old;
    if (m_ui->aspectCheckBox->isChecked())
    {
        if (m_widthState->type == pixelString)
        {
            value = pixelsTo(m_widthState->value, m_heightState->type);
            m_resolutionState->value = i;
            m_widthState->value = toPixels(value, m_heightState->type);

            old = m_ui->widthDoubleSpinBox->blockSignals(true);
            m_ui->widthDoubleSpinBox->setValue(std::round(m_widthState->value));
            m_ui->widthDoubleSpinBox->blockSignals(old);
        }
        else if (m_heightState->type == pixelString)
        {
            value = pixelsTo(m_heightState->value, m_widthState->type);
            m_resolutionState->value = i;
            m_heightState->value = toPixels(value, m_widthState->type);

            old = m_ui->heightDoubleSpinBox->blockSignals(true);
            m_ui->heightDoubleSpinBox->setValue(std::round(m_heightState->value));
            m_ui->heightDoubleSpinBox->blockSignals(old);
        }
    }
    else
        m_resolutionState->value = i;

    updateResolutionSummary();
}

void ImageExporterResolutionWidget::resolutionUnitChanged(const QString& text)
{
    if (text == ppiString)
        m_resolutionState->value = std::ceil(m_resolutionState->value * CM_PER_INCH);
    else
        m_resolutionState->value = std::ceil(m_resolutionState->value * INCH_PER_CM);

    m_ui->resolutionSpinBox->setValue(m_resolutionState->value);
    m_resolutionState->type = text;
}

void ImageExporterResolutionWidget::enableResolution(bool enable)
{
    m_ui->resolutionSpinBox->setEnabled(enable);
    m_ui->resolutionComboBox->setEnabled(enable);
    m_ui->resolutionLabel->setEnabled(enable);
}

ImageExporterResolutionWidget::~ImageExporterResolutionWidget()
{
}

} //namespace gloperate_qtwidgets
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// netsync example program
//
// main.cpp
//
// Copyright (c) 2012-2014 Eric Lombrozo
//
// All Rights Reserved.

#include <CoinCore/CoinNodeData.h>
#include <CoinCore/MerkleTree.h>
#include <CoinCore/typedefs.h>

#include <CoinQ/CoinQ_netsync.h>
#include <CoinQ/CoinQ_coinparams.h>

#include <stdutils/stringutils.h>

#include <logger/logger.h>

#include <signal.h>

bool g_bShutdown = false;

void finish(int sig)
{
    std::cout << "Stopping..." << std::endl;
    g_bShutdown = true;
}

using namespace CoinQ;
using namespace Coin;
using namespace std;

int main(int argc, char* argv[])
{
    try
    {
        NetworkSelector networkSelector;

        if (argc < 3)
        {
            cerr << "# Usage: " << argv[0] << " <network> <host> [port]" << endl
                 << "# Supported networks: " << stdutils::delimited_list(networkSelector.getNetworkNames(), ", ") << endl;
            return -1;
        }

        CoinParams coinParams = networkSelector.getCoinParams(argv[1]);
        string host = argv[2];
        string port = (argc > 3) ? argv[3] : coinParams.default_port();

        cout << endl << "Connecting to " << coinParams.network_name() << " peer" << endl
             << "-------------------------------------------" << endl
             << "  host:             " << host << endl
             << "  port:             " << port << endl
             << "  magic bytes:      " << hex << coinParams.magic_bytes() << endl
             << "  protocol version: " << dec << coinParams.protocol_version() << endl
             << endl;

        INIT_LOGGER("netsync.log");

        signal(SIGINT, &finish);
        signal(SIGTERM, &finish);

        Network::NetworkSync networkSync(coinParams);
        networkSync.loadHeaders("blocktree.dat");
        networkSync.start(host, port);

        networkSync.subscribeStarted([&]() {
            cout << "NetworkSync started." << endl;
        });

        networkSync.subscribeStopped([&]() {
            cout << "NetworkSync stopped." << endl;
        });

        networkSync.subscribeOpen([&]() {
            cout << "NetworkSync open." << endl;
        });

        networkSync.subscribeClose([&]() {
            cout << "NetworkSync closed." << endl;
        });

        networkSync.subscribeTimeout([&]() {
            cout << "NetworkSync timeout." << endl;
        });

        networkSync.subscribeConnectionError([&](const string& error) {
            cout << "NetworkSync connection error: " << error << endl;
        });

        networkSync.subscribeProtocolError([&](const string& error) {
            cout << "NetworkSync protocol error: " << error << endl;
        });

        networkSync.subscribeBlockTreeError([&](const string& error) {
            cout << "NetworkSync block tree error: " << error << endl;
        });

        networkSync.subscribeFetchingHeaders([&]() {
            cout << "NetworkSync fetching headers." << endl;
        });

        networkSync.subscribeHeadersSynched([&]() {
            cout << "NetworkSync headers synched." << endl;
        });

        networkSync.subscribeFetchingBlocks([&]() {
            cout << "NetworkSync fetching blocks." << endl;
        });

        networkSync.subscribeBlocksSynched([&]() {
            cout << "NetworkSync blocks synched." << endl;
        });

        networkSync.subscribeStatus([&](const string& status) {
            cout << "NetworkSync status: " << status << endl;
        });

        networkSync.subscribeTx([&](const Transaction& tx) {
            cout << "NetworkSync transaction:" << tx.getHashLittleEndian().getHex() << endl;
        });

        networkSync.subscribeBlock([&](const ChainBlock& block) {
            cout << "NetworkSync block: " << block.blockHeader.getHashLittleEndian().getHex() << " height: " << block.height << endl;
        });

        networkSync.subscribeMerkleBlock([&](const ChainMerkleBlock& merkleblock) {
            cout << "NetworkSync merkle block: " << merkleblock.blockHeader.getHashLittleEndian().getHex() << " height: " << merkleblock.height << endl;
        });

        networkSync.subscribeAddBestChain([&](const ChainHeader& header) {
            cout << "NetworkSync added to best chain: " << header.getHashLittleEndian().getHex() << " height: " << header.height << endl;
        });

        networkSync.subscribeRemoveBestChain([&](const ChainHeader& header) {
            cout << "NetworkSync removed from best chain: " << header.getHashLittleEndian().getHex() << " height: " << header.height << endl;
        });

        networkSync.subscribeBlockTreeChanged([&]() {
            cout << "NetworkSync block tree changed." << endl;
        });

        networkSync.start(host, port);
        while (!g_bShutdown) { usleep(200); }
        networkSync.stop();
    }
    catch (const exception& e)
    {
        cerr << "Error: " << e.what() << endl;
        return -2;
    }

    return 0;
}
<commit_msg>netsync example working.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// netsync example program
//
// main.cpp
//
// Copyright (c) 2012-2014 Eric Lombrozo
//
// All Rights Reserved.

#include <CoinCore/CoinNodeData.h>
#include <CoinCore/MerkleTree.h>
#include <CoinCore/typedefs.h>

#include <CoinQ/CoinQ_netsync.h>
#include <CoinQ/CoinQ_coinparams.h>

#include <stdutils/stringutils.h>

#include <logger/logger.h>

#include <signal.h>

bool g_bShutdown = false;

void finish(int sig)
{
    std::cout << "Stopping..." << std::endl;
    g_bShutdown = true;
}

using namespace CoinQ;
using namespace Coin;
using namespace std;

int main(int argc, char* argv[])
{
    try
    {
        NetworkSelector networkSelector;

        if (argc < 3)
        {
            cerr << "# Usage: " << argv[0] << " <network> <host> [port]" << endl
                 << "# Supported networks: " << stdutils::delimited_list(networkSelector.getNetworkNames(), ", ") << endl;
            return -1;
        }

        CoinParams coinParams = networkSelector.getCoinParams(argv[1]);
        string host = argv[2];
        string port = (argc > 3) ? argv[3] : coinParams.default_port();

        cout << endl << "Connecting to " << coinParams.network_name() << " peer" << endl
             << "-------------------------------------------" << endl
             << "  host:             " << host << endl
             << "  port:             " << port << endl
             << "  magic bytes:      " << hex << coinParams.magic_bytes() << endl
             << "  protocol version: " << dec << coinParams.protocol_version() << endl
             << endl;

        INIT_LOGGER("netsync.log");
        LOGGER(info) << endl << endl << endl << endl << endl << endl;

        signal(SIGINT, &finish);
        signal(SIGTERM, &finish);

        Network::NetworkSync networkSync(coinParams);
        networkSync.loadHeaders("blocktree.dat", false, [&](const CoinQBlockTreeMem& blocktree) {
            cout << "Best height: " << blocktree.getBestHeight() << " Total work: " << blocktree.getTotalWork().getDec() << endl;
        });

        networkSync.subscribeStarted([&]() {
            cout << "NetworkSync started." << endl;
        });

        networkSync.subscribeStopped([&]() {
            cout << "NetworkSync stopped." << endl;
        });

        networkSync.subscribeOpen([&]() {
            cout << "NetworkSync open." << endl;
        });

        networkSync.subscribeClose([&]() {
            cout << "NetworkSync closed." << endl;
        });

        networkSync.subscribeTimeout([&]() {
            cout << "NetworkSync timeout." << endl;
        });

        networkSync.subscribeConnectionError([&](const string& error) {
            cout << "NetworkSync connection error: " << error << endl;
        });

        networkSync.subscribeProtocolError([&](const string& error) {
            cout << "NetworkSync protocol error: " << error << endl;
        });

        networkSync.subscribeBlockTreeError([&](const string& error) {
            cout << "NetworkSync block tree error: " << error << endl;
        });

        networkSync.subscribeFetchingHeaders([&]() {
            cout << "NetworkSync fetching headers." << endl;
        });

        networkSync.subscribeHeadersSynched([&]() {
            cout << "NetworkSync headers synched." << endl;
        });

        networkSync.subscribeFetchingBlocks([&]() {
            cout << "NetworkSync fetching blocks." << endl;
        });

        networkSync.subscribeBlocksSynched([&]() {
            cout << "NetworkSync blocks synched." << endl;
        });

        networkSync.subscribeStatus([&](const string& status) {
            cout << "NetworkSync status: " << status << endl;
        });

        networkSync.subscribeTx([&](const Transaction& tx) {
            cout << "NetworkSync transaction:" << tx.getHashLittleEndian().getHex() << endl;
        });

        networkSync.subscribeBlock([&](const ChainBlock& block) {
            cout << "NetworkSync block: " << block.blockHeader.getHashLittleEndian().getHex() << " height: " << block.height << endl;
        });

        networkSync.subscribeMerkleBlock([&](const ChainMerkleBlock& merkleblock) {
            cout << "NetworkSync merkle block: " << merkleblock.blockHeader.getHashLittleEndian().getHex() << " height: " << merkleblock.height << endl;
        });

        networkSync.subscribeAddBestChain([&](const ChainHeader& header) {
            cout << "NetworkSync added to best chain: " << header.getHashLittleEndian().getHex() << " height: " << header.height << endl;
        });

        networkSync.subscribeRemoveBestChain([&](const ChainHeader& header) {
            cout << "NetworkSync removed from best chain: " << header.getHashLittleEndian().getHex() << " height: " << header.height << endl;
        });

        networkSync.subscribeBlockTreeChanged([&]() {
            cout << "NetworkSync block tree changed." << endl;
        });

        LOGGER(info) << "Starting..." << endl;
        networkSync.start(host, port);
        while (!g_bShutdown) { usleep(200); }

        LOGGER(info) << "Stopping..." << endl;
        networkSync.stop();
    }
    catch (const exception& e)
    {
        cerr << "Error: " << e.what() << endl;
        return -2;
    }

    return 0;
}
<|endoftext|>