diff --git a/.uncrustify.cfg b/.uncrustify.cfg new file mode 100644 index 0000000000..568bfda207 --- /dev/null +++ b/.uncrustify.cfg @@ -0,0 +1,396 @@ +# -------------------------------------------------------------------------------------------------# +# # +# _ _ _ _ __ ___ _____ _ _ __ _ # +# | | | |_ _ __ _ _ _ _ __| |_(_)/ _|_ _ / __| / / __|| |_ _| |_ __ ___ _ _ / _(_)__ _ # +# | |_| | ' \/ _| '_| || (_-< _| | _| || | | (__ / / (_|_ _|_ _| / _/ _ \ ' \| _| / _` | # +# \___/|_||_\__|_| \_,_/__/\__|_|_| \_, | \___/_/ \___||_| |_| \__\___/_||_|_| |_\__, | # +# |__/ |___/ # +# # +# -------------------------------------------------------------------------------------------------# +# # +# Style: rindeal # +# # +# -------------------------------------------------------------------------------------------------# +# Boilerplate: https://github.com/bengardner/uncrustify/blob/master/etc/defaults.cfg # +# -------------------------------------------------------------------------------------------------# + + +## General +## ------------------------------------------------------------------------------------------------- + +# The type of line endings +newlines = lf # auto/lf/crlf/cr + +code_width = 120 + +# empty_lines_max = nl_max - 1 +nl_max = 3 + + +## UNICODE +## ------------------------------------------------------------------------------------------------- +## Ideally ASCII, UTF-8 otherwise + +# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8 +utf8_byte = false + +# Force the output encoding to UTF-8 +utf8_force = true + + +## Tabs +## ------------------------------------------------------------------------------------------------- +## Always use 4 spaces + +input_tab_size = 4 +output_tab_size = 4 + +indent_with_tabs = 0 + +# Comments that are not a brace level are indented with tabs on a tabstop. +# Requires indent_with_tabs = 2. If false, will use spaces. +indent_cmt_with_tabs = false + +# Whether to use tabs for aligning +align_with_tabs = false + +# Whether to keep non-indenting tabs +align_keep_tabs = false + +# Whether to bump out to the next tab when aligning +align_on_tabstop = false + + +## Indenting +## ------------------------------------------------------------------------------------------------- + +# True: indent_func_call_param will be used (default) +# False: indent_func_call_param will NOT be used. +use_indent_func_call_param = true # false/true + + +# The continuation indent for func_*_param if they are true. +# If non-zero, this overrides the indent. +indent_param = 1 # unsigned number + +# The number of columns to indent per level. +# Usually 2, 3, 4, or 8. +indent_columns = 4 + +# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents. +# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level +indent_continue = 0 + + +## Spacing +## ------------------------------------------------------------------------------------------------- + +# Whether to balance spaces inside nested parens +sp_balance_nested_parens = false + + +## Parentheses +## ------------------------------------------------------------------------------------------------- + +# Controls the indent of a close paren after a newline. +# 0: Indent to body level +# 1: Align under the open paren +# 2: Indent to the brace level +indent_paren_close = 0 + + +## Preprocessor +## ------------------------------------------------------------------------------------------------- + +# Control indent of preprocessors inside #if blocks at brace level 0 +pp_indent = remove # ignore/add/remove/force + +# indent by 1 space +pp_space = add +pp_space_count = 1 + +# indent pp at code level +pp_indent_at_level = true +pp_define_at_level = true + +# Control whether to indent the code between #if, #else and #endif when not at file-level +pp_if_indent_code = false + +# # Align macro functions and variables together +align_pp_define_together = false + +# The minimum space between label and value of a preprocessor define +align_pp_define_gap = 1 + +# The span for aligning on '#define' bodies (0=don't align) +align_pp_define_span = 2 + +# Add or remove space around preprocessor '##' concatenation operator. Default=Add +sp_pp_concat = add # ignore/add/remove/force + +# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force + + +# Template +# -------------------------------------------------------------------------------------------------- + +# Add or remove space in 'template <' vs 'template<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = add # ignore/add/remove/force + +# Add or remove space before '<>' +sp_before_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<' and '>' +sp_inside_angle = remove # ignore/add/remove/force + +# Add or remove space after '<>' +sp_after_angle = add # ignore/add/remove/force + +# Add or remove space between '<>' and '(' as found in 'new List();' +sp_angle_paren = remove # ignore/add/remove/force + +# Add or remove space between '<>' and a word as in 'List m;' +sp_angle_word = add # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add +sp_angle_shift = add # ignore/add/remove/force + + + + + +indent_align_string = false + +# Whether braces are indented to the body level +indent_braces = false +# Disabled indenting function braces if indent_braces is true +indent_braces_no_func = false +# Disabled indenting class braces if indent_braces is true +indent_braces_no_class = false +# Disabled indenting struct braces if indent_braces is true +indent_braces_no_struct = false +# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false + +indent_namespace = false +indent_extern = false +indent_class = true +indent_class_colon = false +indent_else_if = false +indent_var_def_cont = true + +indent_func_call_param = false +indent_func_def_param = true +indent_func_proto_param = true +indent_func_class_param = false +indent_func_ctor_var_param = false +indent_func_param_double = true + +indent_template_param = false +indent_relative_single_line_comments = false +indent_col1_comment = true +indent_access_spec_body = false +indent_paren_nl = false +indent_comma_paren = false +indent_bool_paren = false +indent_first_bool_expr = false +indent_square_nl = false +indent_preserve_sql = false +indent_align_assign = true + +#align_number_left = true +align_func_params = true +align_same_func_call_params = false +align_var_def_colon = false +align_var_def_attribute = true +align_var_def_inline = true +align_right_cmt_mix = false +align_on_operator = false +align_mix_var_proto = false +align_single_line_func = false +align_single_line_brace = false +align_nl_cont = false +align_left_shift = true +align_oc_decl_colon = false + +nl_collapse_empty_body = true +nl_assign_leave_one_liners = true +nl_class_leave_one_liners = true +nl_enum_leave_one_liners = true +nl_getset_leave_one_liners = true +nl_func_leave_one_liners = true +nl_if_leave_one_liners = true +nl_multi_line_cond = true +nl_multi_line_define = true +nl_before_case = false +nl_after_case = false +nl_after_return = true +nl_after_semicolon = true +nl_after_brace_open = false +nl_after_brace_open_cmt = false +nl_after_vbrace_open = false +nl_after_vbrace_open_empty = false +nl_after_brace_close = false +nl_after_vbrace_close = false +nl_define_macro = false +nl_squeeze_ifdef = false +nl_ds_struct_enum_cmt = false +nl_ds_struct_enum_close_brace = false +nl_create_if_one_liner = false +nl_create_for_one_liner = false +nl_create_while_one_liner = false +ls_for_split_full = true +ls_func_split_full = false +nl_after_multiline_comment = true +eat_blanks_after_open_brace = true +eat_blanks_before_close_brace = true +mod_full_brace_if_chain = true +mod_pawn_semicolon = false +mod_full_paren_if_bool = false +mod_remove_extra_semicolon = false +mod_sort_import = false +mod_sort_using = false +mod_sort_include = false +mod_move_case_break = false +mod_remove_empty_return = true +cmt_indent_multi = true +cmt_c_group = false +cmt_c_nl_start = false +cmt_c_nl_end = false +cmt_cpp_group = false +cmt_cpp_nl_start = false +cmt_cpp_nl_end = false +cmt_cpp_to_c = false +cmt_star_cont = true +cmt_multi_check_last = true +cmt_insert_before_preproc = false +indent_sing_line_comments = 0 +indent_switch_case = 4 +indent_case_shift = 0 + +align_var_def_star_style = 0 +align_var_def_amp_style = 1 +align_assign_span = 1 +align_assign_thresh = 8 +align_enum_equ_span = 3 +align_var_struct_span = 3 +align_var_struct_gap = 1 +align_struct_init_span = 2 +align_right_cmt_span = 2 +align_right_cmt_gap = 1 +align_right_cmt_at_col = 2 + +nl_end_of_file_min = 1 +nl_func_var_def_blk = 0 +nl_after_func_body = 2 +nl_after_func_body_one_liner = 1 +nl_before_block_comment = 2 +nl_after_struct = 1 +mod_full_brace_nl = 1 +mod_add_long_function_closebrace_comment = 32 +mod_add_long_ifdef_endif_comment = 10 +mod_add_long_ifdef_else_comment = 10 +sp_arith = force +sp_assign = force +sp_assign_default = add +sp_enum_assign = force +sp_bool = force +sp_compare = force +sp_before_ptr_star = add +sp_before_unnamed_ptr_star = add +sp_between_ptr_star = remove +sp_after_ptr_star = remove +sp_after_ptr_star_func = force +sp_before_ptr_star_func = force +sp_after_type = force +sp_before_sparen = force +sp_inside_sparen = remove +sp_after_sparen = add +sp_sparen_brace = add +sp_special_semi = remove +sp_before_semi = remove +sp_before_semi_for_empty = remove +sp_after_semi = add +sp_after_semi_for_empty = remove +sp_after_comma = force +sp_before_comma = remove +sp_before_case_colon = remove +sp_after_operator = add +sp_after_operator_sym = add +sp_after_cast = add +sp_inside_paren_cast = remove +sp_sizeof_paren = remove +sp_inside_braces_enum = add +sp_inside_braces_struct = add +sp_inside_braces = add +sp_inside_braces_empty = add +sp_func_proto_paren = remove +sp_func_def_paren = remove +sp_inside_fparens = remove +sp_inside_fparen = remove +sp_fparen_brace = remove +sp_func_call_paren = remove +sp_func_call_paren_empty = remove +sp_func_call_user_paren = remove +sp_return_paren = add +sp_attribute_paren = remove +sp_defined_paren = remove +sp_macro = add +sp_macro_func = add +sp_else_brace = add +sp_brace_else = add +sp_brace_typedef = add +sp_not = remove +sp_inv = remove +sp_addr = remove +sp_member = remove +sp_deref = remove +sp_sign = remove +sp_incdec = remove +sp_before_nl_cont = add +sp_cond_colon = force +sp_cond_question = force +sp_cmt_cpp_start = add +nl_start_of_file = remove +nl_end_of_file = force +nl_assign_brace = remove +nl_assign_square = remove +nl_enum_brace = remove +nl_struct_brace = remove +nl_union_brace = remove +nl_if_brace = remove +nl_brace_else = remove +nl_elseif_brace = remove +nl_else_brace = remove +nl_else_if = remove +nl_for_brace = remove +nl_while_brace = remove +nl_do_brace = remove +nl_brace_while = remove +nl_switch_brace = remove +nl_case_colon_brace = remove +nl_func_type_name = remove +nl_func_proto_type_name = remove +nl_func_paren = remove +nl_func_def_paren = remove +nl_func_decl_empty = remove +nl_func_def_empty = remove +nl_fdef_brace = add +nl_return_expr = remove +pos_arith = lead +pos_assign = trail +pos_bool = trail +pos_conditional = trail +pos_comma = trail +pos_class_comma = lead +pos_class_colon = lead +mod_full_brace_do = remove +mod_full_brace_for = remove +mod_full_brace_function = force +mod_full_brace_while = remove +mod_paren_on_return = ignore diff --git a/plugins/tools/selectiontools/KisMagneticGraph.h b/plugins/tools/selectiontools/KisMagneticGraph.h index 46b2b86cf8..d668acdcee 100644 --- a/plugins/tools/selectiontools/KisMagneticGraph.h +++ b/plugins/tools/selectiontools/KisMagneticGraph.h @@ -1,263 +1,277 @@ /* * Copyright (c) 2019 Kuntal Majumder * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISMAGNETICGRAPH_H #define KISMAGNETICGRAPH_H #include #include #include #include #include #include #include struct VertexDescriptor { - - long x,y; + long x, y; enum Direction { MIN = 0, - N = MIN, S, E, W, NW, NE, SW, SE, NONE + N = MIN, S, E, W, NW, NE, SW, SE, NONE }; - VertexDescriptor(long _x, long _y): + VertexDescriptor(long _x, long _y) : x(_x), y(_y) { } - VertexDescriptor(QPoint pt): + VertexDescriptor(QPoint pt) : x(pt.x()), y(pt.y()) { } - VertexDescriptor(): + VertexDescriptor() : x(0), y(0) { } - bool operator==(VertexDescriptor const &rhs) const { + bool operator == (VertexDescriptor const &rhs) const + { return rhs.x == x && rhs.y == y; } - bool operator==(QPoint const &rhs) const { + bool operator == (QPoint const &rhs) const + { return rhs.x() == x && rhs.y() == y; } - bool operator !=(VertexDescriptor const &rhs) const { + bool operator != (VertexDescriptor const &rhs) const + { return rhs.x != x || rhs.y != y; } - bool operator<(VertexDescriptor const &rhs) const { + bool operator < (VertexDescriptor const &rhs) const + { return x < rhs.x || (x == rhs.x && y < rhs.y); } // returns one of the 8 neighboring pixel based on the direction // it gives out multiple warnings, but I am lazy, sorry - VertexDescriptor neighbor(Direction direction) const { - + VertexDescriptor neighbor(Direction direction) const + { int dx = 0, dy = 0; - switch (direction){ - case W: - case SW: - case NW: - dx = -1; - break; - case E: - case SE: - case NE: - dx = 1; + switch (direction) { + case W: + case SW: + case NW: + dx = -1; + break; + case E: + case SE: + case NE: + dx = 1; } - switch(direction){ - case N: - case NW: - case NE: - dy = -1; - break; - case S: - case SW: - case SE: - dy = 1; + switch (direction) { + case N: + case NW: + case NE: + dy = -1; + break; + case S: + case SW: + case SE: + dy = 1; } VertexDescriptor const neighbor(x + dx, y + dy); return neighbor; } }; -QDebug operator<<(QDebug dbg, const VertexDescriptor &v) { +QDebug operator << (QDebug dbg, const VertexDescriptor &v) +{ dbg.nospace() << "(" << v.x << ", " << v.y << ")"; return dbg.space(); } struct neighbour_iterator; -struct KisMagneticGraph{ - +struct KisMagneticGraph { typedef KisMagneticGraph type; - KisMagneticGraph() { } + KisMagneticGraph(){ } - KisMagneticGraph(KisPaintDeviceSP dev): + KisMagneticGraph(KisPaintDeviceSP dev) : m_dev(dev) { m_randAccess = m_dev->createRandomAccessorNG(m_dev->exactBounds().x(), m_dev->exactBounds().y()); } - KisMagneticGraph(KisPaintDeviceSP dev, QRect graphRect): + KisMagneticGraph(KisPaintDeviceSP dev, QRect graphRect) : m_rect(graphRect), m_dev(dev) { m_randAccess = m_dev->createRandomAccessorNG(m_dev->exactBounds().x(), m_dev->exactBounds().y()); } - typedef VertexDescriptor vertex_descriptor; + typedef VertexDescriptor vertex_descriptor; typedef std::pair edge_descriptor; - typedef boost::undirected_tag directed_category; - typedef boost::disallow_parallel_edge_tag edge_parallel_category; - typedef boost::incidence_graph_tag traversal_category; - typedef neighbour_iterator out_edge_iterator; - typedef unsigned degree_size_type; + typedef boost::undirected_tag directed_category; + typedef boost::disallow_parallel_edge_tag edge_parallel_category; + typedef boost::incidence_graph_tag traversal_category; + typedef neighbour_iterator out_edge_iterator; + typedef unsigned degree_size_type; - quint8 getIntensity(VertexDescriptor pt) { + quint8 getIntensity(VertexDescriptor pt) + { m_randAccess->moveTo(pt.x, pt.y); quint8 val = *(m_randAccess->rawData()); return val; } - unsigned outDegree(VertexDescriptor pt){ - //corners - if(pt == m_rect.topLeft() || pt == m_rect.topRight() || - pt == m_rect.bottomLeft() || pt == m_rect.bottomRight()){ - if(m_rect.width() == 1 || m_rect.height() == 1) + unsigned outDegree(VertexDescriptor pt) + { + // corners + if (pt == m_rect.topLeft() || pt == m_rect.topRight() || + pt == m_rect.bottomLeft() || pt == m_rect.bottomRight()) + { + if (m_rect.width() == 1 || m_rect.height() == 1) return 1; + return 3; } - //edges - if(pt.x == m_rect.topLeft().x() || pt.y == m_rect.topLeft().y() || - pt.x == m_rect.bottomRight().x() || pt.y == m_rect.bottomRight().y()){ - if(m_rect.width() == 1 || m_rect.height() == 1) + // edges + if (pt.x == m_rect.topLeft().x() || pt.y == m_rect.topLeft().y() || + pt.x == m_rect.bottomRight().x() || pt.y == m_rect.bottomRight().y()) + { + if (m_rect.width() == 1 || m_rect.height() == 1) return 2; + return 5; } return 8; } - QRect m_rect; + QRect m_rect; private: - KisPaintDeviceSP m_dev; + KisPaintDeviceSP m_dev; KisRandomAccessorSP m_randAccess; }; -struct neighbour_iterator : public boost::iterator_facade, - boost::forward_traversal_tag, - std::pair> -{ - - neighbour_iterator(VertexDescriptor v, KisMagneticGraph g, VertexDescriptor::Direction d): +struct neighbour_iterator : public boost::iterator_facade + , boost::forward_traversal_tag + , std::pair > { + neighbour_iterator(VertexDescriptor v, KisMagneticGraph g, VertexDescriptor::Direction d) : m_point(v), m_direction(d), m_graph(g) { } neighbour_iterator() { } - std::pair - operator*() const { - std::pair const result = std::make_pair(m_point, m_point.neighbor(m_direction)); + std::pair operator * () const + { + std::pair const result = std::make_pair(m_point, m_point.neighbor(m_direction)); return result; } - void operator++() { - m_direction = static_cast(int(m_direction)+1); + void operator ++ () + { + m_direction = static_cast(int(m_direction) + 1); VertexDescriptor next = m_point.neighbor(m_direction); - if(m_direction == VertexDescriptor::NONE){ + if (m_direction == VertexDescriptor::NONE) { return; } - if(!m_graph.m_rect.contains(next.x, next.y)){ - operator++(); + if (!m_graph.m_rect.contains(next.x, next.y)) { + operator ++ (); } } - bool operator==(neighbour_iterator const& that) const { + bool operator == (neighbour_iterator const& that) const + { return m_point == that.m_point && m_direction == that.m_direction; } - bool equal(neighbour_iterator const& that) const { - return operator==(that); + bool equal(neighbour_iterator const& that) const + { + return operator == (that); } - void increment() { - operator++(); + void increment() + { + operator ++ (); } private: - VertexDescriptor m_point; + VertexDescriptor m_point; VertexDescriptor::Direction m_direction; - KisMagneticGraph m_graph; + KisMagneticGraph m_graph; }; // Requirements for an Incidence Graph, // https://www.boost.org/doc/libs/1_70_0/libs/graph/doc/IncidenceGraph.html -namespace boost{ -template<> +namespace boost { +template <> struct graph_traits { - typedef typename KisMagneticGraph::vertex_descriptor vertex_descriptor; - typedef typename KisMagneticGraph::edge_descriptor edge_descriptor; - typedef typename KisMagneticGraph::out_edge_iterator out_edge_iterator; - typedef typename KisMagneticGraph::directed_category directed_category; + typedef typename KisMagneticGraph::vertex_descriptor vertex_descriptor; + typedef typename KisMagneticGraph::edge_descriptor edge_descriptor; + typedef typename KisMagneticGraph::out_edge_iterator out_edge_iterator; + typedef typename KisMagneticGraph::directed_category directed_category; typedef typename KisMagneticGraph::edge_parallel_category edge_parallel_category; - typedef typename KisMagneticGraph::traversal_category traversal_category; - typedef typename KisMagneticGraph::degree_size_type degree_size_type; + typedef typename KisMagneticGraph::traversal_category traversal_category; + typedef typename KisMagneticGraph::degree_size_type degree_size_type; typedef void in_edge_iterator; typedef void vertex_iterator; typedef void vertices_size_type; typedef void edge_iterator; typedef void edges_size_type; }; } -typename KisMagneticGraph::vertex_descriptor -source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g) { +typename KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g) +{ Q_UNUSED(g) return e.first; } -typename KisMagneticGraph::vertex_descriptor -target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g) { +typename KisMagneticGraph::vertex_descriptor target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g) +{ Q_UNUSED(g) return e.second; } -std::pair -out_edges(typename KisMagneticGraph::vertex_descriptor v, KisMagneticGraph g) { +std::pair out_edges( + typename KisMagneticGraph::vertex_descriptor v, KisMagneticGraph g) +{ return std::make_pair( - KisMagneticGraph::out_edge_iterator(v, g, VertexDescriptor::Direction::MIN), - KisMagneticGraph::out_edge_iterator(v, g, VertexDescriptor::Direction::NONE) - ); + KisMagneticGraph::out_edge_iterator(v, g, VertexDescriptor::Direction::MIN), + KisMagneticGraph::out_edge_iterator(v, g, VertexDescriptor::Direction::NONE) + ); } -typename KisMagneticGraph::degree_size_type -out_degree(typename KisMagneticGraph::vertex_descriptor v, KisMagneticGraph g) { +typename KisMagneticGraph::degree_size_type out_degree(typename KisMagneticGraph::vertex_descriptor v, + KisMagneticGraph g) +{ return g.outDegree(v); } -#endif +#endif // ifndef KISMAGNETICGRAPH_H diff --git a/plugins/tools/selectiontools/KisMagneticWorker.cc b/plugins/tools/selectiontools/KisMagneticWorker.cc index b4adb299c4..da5079879a 100644 --- a/plugins/tools/selectiontools/KisMagneticWorker.cc +++ b/plugins/tools/selectiontools/KisMagneticWorker.cc @@ -1,195 +1,202 @@ /* * Copyright (c) 2019 Kuntal Majumder * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisMagneticWorker.h" #include #include #include #include #include #include #include #include "KisMagneticGraph.h" struct DistanceMap { typedef VertexDescriptor key_type; typedef double data_type; typedef std::pair value_type; explicit DistanceMap(double const& dval) - : m_default(dval) + : m_default(dval) { } - data_type &operator[](key_type const& k) { + data_type &operator [] (key_type const& k) + { if (m.find(k) == m.end()) m[k] = m_default; return m[k]; } private: std::map m; - data_type const m_default; + data_type const m_default; }; -struct PredecessorMap{ +struct PredecessorMap { PredecessorMap() = default; PredecessorMap(PredecessorMap const& that) = default; typedef VertexDescriptor key_type; typedef VertexDescriptor value_type; typedef boost::read_write_property_map_tag category; - VertexDescriptor &operator[](VertexDescriptor v){ + VertexDescriptor &operator [] (VertexDescriptor v) + { return m_map[v]; } std::map m_map; }; -VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v){ +VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v) +{ auto found = m.m_map.find(v); return found != m.m_map.end() ? found->second : v; } -void put(PredecessorMap &m, VertexDescriptor key, VertexDescriptor value){ +void put(PredecessorMap &m, VertexDescriptor key, VertexDescriptor value) +{ m.m_map[key] = value; } -double EuclideanDistance(VertexDescriptor p1, VertexDescriptor p2){ - return std::sqrt(std::pow(p1.y-p2.y, 2) + std::pow(p1.x-p2.x, 2)); +double EuclideanDistance(VertexDescriptor p1, VertexDescriptor p2) +{ + return std::sqrt(std::pow(p1.y - p2.y, 2) + std::pow(p1.x - p2.x, 2)); } class AStarHeuristic : public boost::astar_heuristic { - private: - VertexDescriptor m_goal; +private: + VertexDescriptor m_goal; - public: - explicit AStarHeuristic(VertexDescriptor goal): - m_goal(goal) - { } +public: + explicit AStarHeuristic(VertexDescriptor goal) : + m_goal(goal) + { } - double operator()(VertexDescriptor v) { - return EuclideanDistance(v,m_goal); - } + double operator () (VertexDescriptor v) + { + return EuclideanDistance(v, m_goal); + } }; -struct GoalFound {}; +struct GoalFound { }; class AStarGoalVisitor : public boost::default_astar_visitor { - public: - explicit AStarGoalVisitor(VertexDescriptor goal) : m_goal(goal) { } - - void examine_vertex(VertexDescriptor u, KisMagneticGraph const &g) { - Q_UNUSED(g) - if(u == m_goal){ - throw GoalFound(); - } +public: + explicit AStarGoalVisitor(VertexDescriptor goal) : m_goal(goal){ } + + void examine_vertex(VertexDescriptor u, KisMagneticGraph const &g) + { + Q_UNUSED(g) + if (u == m_goal) { + throw GoalFound(); } + } - private: - VertexDescriptor m_goal; +private: + VertexDescriptor m_goal; }; -struct WeightMap{ +struct WeightMap { typedef std::pair key_type; typedef double data_type; typedef std::pair value_type; WeightMap() = default; - explicit WeightMap(const KisMagneticGraph &g): + explicit WeightMap(const KisMagneticGraph &g) : m_graph(g) { } - data_type& operator[](key_type const& k) { + data_type& operator [] (key_type const& k) + { if (m_map.find(k) == m_map.end()) { - double edge_gradient = (m_graph.getIntensity(k.first) + m_graph.getIntensity(k.second))/2; + double edge_gradient = (m_graph.getIntensity(k.first) + m_graph.getIntensity(k.second)) / 2; m_map[k] = EuclideanDistance(k.first, k.second) / (edge_gradient + 1); } return m_map[k]; } private: std::map m_map; - KisMagneticGraph m_graph; + KisMagneticGraph m_graph; }; KisMagneticWorker::KisMagneticWorker(const KisPaintDeviceSP& dev) -{ +{ KisPaintDeviceSP m_dev = KisPainter::convertToAlphaAsGray(dev); KisPainter::copyAreaOptimized(dev->exactBounds().topLeft(), dev, m_dev, dev->exactBounds()); KisGaussianKernel::applyLoG(m_dev, m_dev->exactBounds(), 2, -1.0, QBitArray(), nullptr); KisLazyFillTools::normalizeAlpha8Device(m_dev, m_dev->exactBounds()); m_graph = new KisMagneticGraph(m_dev); } -QVector KisMagneticWorker::computeEdge(int radius, QPoint begin, QPoint end) { - +QVector KisMagneticWorker::computeEdge(int radius, QPoint begin, QPoint end) +{ QRect rect; - KisAlgebra2D::accumulateBounds(QVector{begin, end}, &rect); - rect.setSize(rect.size()*radius); + KisAlgebra2D::accumulateBounds(QVector { begin, end }, &rect); + rect.setSize(rect.size() * radius); VertexDescriptor goal(end); VertexDescriptor start(begin); m_graph->m_rect = rect; // How many maps does it require? // Take a look here, if it doesn't make sense, https://www.boost.org/doc/libs/1_70_0/libs/graph/doc/astar_search.html PredecessorMap pmap; DistanceMap dmap(std::numeric_limits::max()); dmap[start] = 0; std::map rmap; std::map cmap; std::map imap; WeightMap wmap(*m_graph); AStarHeuristic heuristic(goal); QVector result; try{ boost::astar_search_no_init( - *m_graph, start, heuristic - ,boost::visitor(AStarGoalVisitor(goal)) - .distance_map(boost::associative_property_map(dmap)) - .predecessor_map(boost::ref(pmap)) - .weight_map(boost::associative_property_map(wmap)) - .vertex_index_map(boost::associative_property_map>(imap)) - .rank_map(boost::associative_property_map>(rmap)) - .color_map(boost::associative_property_map>(cmap)) - .distance_combine(std::plus()) - .distance_compare(std::less()) - ); - - }catch(GoalFound const&){ - for(VertexDescriptor u=goal; u!=start; u = pmap[u]){ - result.push_front(QPointF(u.x,u.y)); + *m_graph, start, heuristic, + boost::visitor(AStarGoalVisitor(goal)) + .distance_map(boost::associative_property_map(dmap)) + .predecessor_map(boost::ref(pmap)) + .weight_map(boost::associative_property_map(wmap)) + .vertex_index_map(boost::associative_property_map >(imap)) + .rank_map(boost::associative_property_map >(rmap)) + .color_map(boost::associative_property_map >(cmap)) + .distance_combine(std::plus()) + .distance_compare(std::less()) + ); + }catch (GoalFound const&) { + for (VertexDescriptor u = goal; u != start; u = pmap[u]) { + result.push_front(QPointF(u.x, u.y)); } } - result.push_front(QPoint(start.x,start.y)); + result.push_front(QPoint(start.x, start.y)); return result; -} +} // KisMagneticWorker::computeEdge quint8 KisMagneticWorker::intensity(QPoint pt) { return m_graph->getIntensity(VertexDescriptor(pt)); } diff --git a/plugins/tools/selectiontools/KisMagneticWorker.h b/plugins/tools/selectiontools/KisMagneticWorker.h index 17497b37d4..969600a667 100644 --- a/plugins/tools/selectiontools/KisMagneticWorker.h +++ b/plugins/tools/selectiontools/KisMagneticWorker.h @@ -1,41 +1,42 @@ /* * Copyright (c) 2019 Kuntal Majumder * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISMAGNETICWORKER_H #define KISMAGNETICWORKER_H #include #include class KisMagneticGraph; -class KRITASELECTIONTOOLS_EXPORT KisMagneticWorker{ +class KRITASELECTIONTOOLS_EXPORT KisMagneticWorker { public: - KisMagneticWorker() { - //Do not use this, just for making the compiler happy + KisMagneticWorker() + { + // Do not use this, just for making the compiler happy } KisMagneticWorker(const KisPaintDeviceSP &dev); QVector computeEdge(int radius, QPoint start, QPoint end); quint8 intensity(QPoint pt); private: KisMagneticGraph *m_graph; }; -#endif +#endif // ifndef KISMAGNETICWORKER_H diff --git a/plugins/tools/selectiontools/KisToolSelectMagnetic.cc b/plugins/tools/selectiontools/KisToolSelectMagnetic.cc index 1daef55f6f..43aa9fc356 100644 --- a/plugins/tools/selectiontools/KisToolSelectMagnetic.cc +++ b/plugins/tools/selectiontools/KisToolSelectMagnetic.cc @@ -1,373 +1,373 @@ /* * Copyright (c) 2019 Kuntal Majumder * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisToolSelectMagnetic.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_painter.h" #include #include "canvas/kis_canvas2.h" #include "kis_pixel_selection.h" #include "kis_selection_tool_helper.h" #include "kis_algebra_2d.h" #include #define FEEDBACK_LINE_WIDTH 2 KisToolSelectMagnetic::KisToolSelectMagnetic(KoCanvasBase *canvas) : KisToolSelect(canvas, KisCursor::load("tool_magnetic_selection_cursor.png", 5, 5), i18n("Magnetic Selection")), - m_continuedMode(false), m_complete(true), m_radius(20), m_threshold(100), m_checkPoint(-1) + m_continuedMode(false), m_complete(true), m_radius(20), m_threshold(100), m_checkPoint(-1) { } void KisToolSelectMagnetic::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Control) { m_continuedMode = true; } KisToolSelect::keyPressEvent(event); } void KisToolSelectMagnetic::keyReleaseEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Control || - !(event->modifiers() & Qt::ControlModifier)) { - + !(event->modifiers() & Qt::ControlModifier)) + { m_continuedMode = false; if (mode() != PAINT_MODE && !m_points.isEmpty()) { finishSelectionAction(); } } KisToolSelect::keyReleaseEvent(event); } -//the cursor is still tracked even when no mousebutton is pressed +// the cursor is still tracked even when no mousebutton is pressed void KisToolSelectMagnetic::mouseMoveEvent(KoPointerEvent *event) { KisToolSelect::mouseMoveEvent(event); - if(m_complete) + if (m_complete) return; m_lastCursorPos = convertToPixelCoord(event); - QPoint current((int)m_lastCursorPos.x(), (int)m_lastCursorPos.y()); + QPoint current((int) m_lastCursorPos.x(), (int) m_lastCursorPos.y()); vQPointF pointSet = m_worker.computeEdge(m_radius, m_lastAnchor, current); - m_points.resize(m_checkPoint+1); + m_points.resize(m_checkPoint + 1); m_points.append(pointSet); int lastCheckPoint = m_checkPoint; - for(int i=m_points.count()-1; i>m_checkPoint; i--){ + for (int i = m_points.count() - 1; i > m_checkPoint; i--) { QPoint pointInQuestion(m_points[i].toPoint()); - if(m_worker.intensity(pointInQuestion) >= m_threshold){ + if (m_worker.intensity(pointInQuestion) >= m_threshold) { m_checkPoint = i; m_lastAnchor = pointInQuestion; break; } } - for(int i=lastCheckPoint; i < m_checkPoint; i++){ + for (int i = lastCheckPoint; i < m_checkPoint; i++) { int temp = m_checkPoint - i; - if(temp%m_radius == 0 && temp != 0){ + if (temp % m_radius == 0 && temp != 0) { m_lastAnchor = m_points[i].toPoint(); m_anchorPoints.push_back(i); } } m_paintPath = QPainterPath(); m_paintPath.moveTo(pixelToView(m_points[0])); - for(int i=1; i 0 && m_snapBound.contains(m_lastAnchor)){ + if (m_anchorPoints.count() > 0 && m_snapBound.contains(m_lastAnchor)) { m_complete = true; finishSelectionAction(); return; } m_anchorPoints.push_back(m_checkPoint); m_complete = false; } -//drag while primary mouse button is pressed +// drag while primary mouse button is pressed void KisToolSelectMagnetic::continuePrimaryAction(KoPointerEvent *event) { KisToolSelectBase::continuePrimaryAction(event); } -//release primary mouse button +// release primary mouse button void KisToolSelectMagnetic::endPrimaryAction(KoPointerEvent *event) { KisToolSelectBase::endPrimaryAction(event); } void KisToolSelectMagnetic::finishSelectionAction() { - KisCanvas2 * kisCanvas = dynamic_cast(canvas()); + KisCanvas2 *kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas); kisCanvas->updateCanvas(); setMode(KisTool::HOVER_MODE); QRectF boundingViewRect = pixelToView(KisAlgebra2D::accumulateBounds(m_points)); KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Outline")); if (m_points.count() > 2 && - !helper.tryDeselectCurrentSelection(boundingViewRect, selectionAction())) { + !helper.tryDeselectCurrentSelection(boundingViewRect, selectionAction())) + { QApplication::setOverrideCursor(KisCursor::waitCursor()); const SelectionMode mode = helper.tryOverrideSelectionMode(kisCanvas->viewManager()->selection(), selectionMode(), selectionAction()); if (mode == PIXEL_SELECTION) { - KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection()); KisPainter painter(tmpSel); painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); painter.setAntiAliasPolygonFill(antiAliasSelection()); painter.setFillStyle(KisPainter::FillStyleForegroundColor); painter.setStrokeStyle(KisPainter::StrokeStyleNone); painter.paintPolygon(m_points); QPainterPath cache; cache.addPolygon(m_points); cache.closeSubpath(); tmpSel->setOutlineCache(cache); helper.selectPixelSelection(tmpSel, selectionAction()); } else { - - KoPathShape* path = new KoPathShape(); + KoPathShape *path = new KoPathShape(); path->setShapeId(KoPathShapeId); QTransform resolutionMatrix; resolutionMatrix.scale(1 / currentImage()->xRes(), 1 / currentImage()->yRes()); path->moveTo(resolutionMatrix.map(m_points[0])); for (int i = 1; i < m_points.count(); i++) path->lineTo(resolutionMatrix.map(m_points[i])); path->close(); path->normalize(); helper.addSelectionShape(path, selectionAction()); } QApplication::restoreOverrideCursor(); } m_points.clear(); m_anchorPoints.clear(); m_paintPath = QPainterPath(); -} +} // KisToolSelectMagnetic::finishSelectionAction void KisToolSelectMagnetic::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); if ((mode() == KisTool::PAINT_MODE || m_continuedMode) && - !m_points.isEmpty()) { - + !m_points.isEmpty()) + { QPainterPath outline = m_paintPath; if (m_continuedMode && mode() != KisTool::PAINT_MODE) { outline.lineTo(pixelToView(m_lastCursorPos)); } paintToolOutline(&gc, outline); - Q_FOREACH(const int pt, m_anchorPoints){ - QRect tempRect(QPoint(0,0),QSize(1, 1)); + Q_FOREACH (const int pt, m_anchorPoints) { + QRect tempRect(QPoint(0, 0), QSize(1, 1)); tempRect.moveTo(m_points[pt].toPoint()); gc.drawRect(pixelToView(tempRect)); } } } void KisToolSelectMagnetic::updateFeedback() { if (m_points.count() > 1) { qint32 lastPointIndex = m_points.count() - 1; QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_points[lastPointIndex]).normalized(); updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH); updateCanvasPixelRect(updateRect); } } void KisToolSelectMagnetic::updateContinuedMode() { if (!m_points.isEmpty()) { qint32 lastPointIndex = m_points.count() - 1; QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_lastCursorPos).normalized(); updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH); updateCanvasPixelRect(updateRect); } } -void KisToolSelectMagnetic::activate(KoToolBase::ToolActivation activation, const QSet &shapes) +void KisToolSelectMagnetic::activate(KoToolBase::ToolActivation activation, const QSet &shapes) { - m_worker = KisMagneticWorker(image()->projection()); - m_configGroup = KSharedConfig::openConfig()->group(toolId()); + m_worker = KisMagneticWorker(image()->projection()); + m_configGroup = KSharedConfig::openConfig()->group(toolId()); KisToolSelect::activate(activation, shapes); } void KisToolSelectMagnetic::deactivate() { - KisCanvas2 * kisCanvas = dynamic_cast(canvas()); + KisCanvas2 *kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas); kisCanvas->updateCanvas(); m_continuedMode = false; - m_complete = true; + m_complete = true; KisTool::deactivate(); } void KisToolSelectMagnetic::requestUndoDuringStroke() { - if(m_complete) return; + if (m_complete) return; + m_anchorPoints.pop_back(); m_lastAnchor = m_points[m_anchorPoints.last()].toPoint(); m_checkPoint = m_anchorPoints.last(); updateCanvasPixelRect(image()->bounds()); } void KisToolSelectMagnetic::requestStrokeEnd() { - if(m_complete) return; + if (m_complete) return; + m_complete = true; finishSelectionAction(); } void KisToolSelectMagnetic::requestStrokeCancellation() { setMode(KisTool::HOVER_MODE); m_complete = true; m_points.clear(); m_anchorPoints.clear(); m_paintPath = QPainterPath(); updateCanvasPixelRect(image()->bounds()); } -QWidget* KisToolSelectMagnetic::createOptionWidget() +QWidget * KisToolSelectMagnetic::createOptionWidget() { KisToolSelectBase::createOptionWidget(); KisSelectionOptions *selectionWidget = selectionOptionWidget(); - QHBoxLayout* f1 = new QHBoxLayout(); - QLabel * lblRad = new QLabel(i18n("Radius: "), selectionWidget); + QHBoxLayout *f1 = new QHBoxLayout(); + QLabel *lblRad = new QLabel(i18n("Radius: "), selectionWidget); f1->addWidget(lblRad); - KisSliderSpinBox* radInput = new KisSliderSpinBox(selectionWidget); + KisSliderSpinBox *radInput = new KisSliderSpinBox(selectionWidget); radInput->setObjectName("radius"); radInput->setRange(20, 200); radInput->setSingleStep(10); f1->addWidget(radInput); connect(radInput, SIGNAL(valueChanged(int)), this, SLOT(slotSetRadius(int))); - QHBoxLayout* f2 = new QHBoxLayout(); - QLabel * lblThreshold = new QLabel(i18n("Threshold: "), selectionWidget); + QHBoxLayout *f2 = new QHBoxLayout(); + QLabel *lblThreshold = new QLabel(i18n("Threshold: "), selectionWidget); f2->addWidget(lblThreshold); - KisSliderSpinBox* threshInput = new KisSliderSpinBox(selectionWidget); + KisSliderSpinBox *threshInput = new KisSliderSpinBox(selectionWidget); threshInput->setObjectName("threshold"); threshInput->setRange(60, 200); threshInput->setSingleStep(10); f2->addWidget(threshInput); connect(threshInput, SIGNAL(valueChanged(int)), this, SLOT(slotSetThreshold(int))); - QVBoxLayout* l = dynamic_cast(selectionWidget->layout()); + QVBoxLayout *l = dynamic_cast(selectionWidget->layout()); Q_ASSERT(l); l->insertLayout(1, f1); l->insertLayout(2, f2); radInput->setValue(m_configGroup.readEntry("radius", 20)); threshInput->setValue(m_configGroup.readEntry("threshold", 100)); return selectionWidget; -} +} // KisToolSelectMagnetic::createOptionWidget void KisToolSelectMagnetic::slotSetRadius(int r) { m_radius = r; m_configGroup.writeEntry("radius", r); } void KisToolSelectMagnetic::slotSetThreshold(int t) { m_threshold = t; m_configGroup.writeEntry("threshold", t); } void KisToolSelectMagnetic::resetCursorStyle() { if (selectionAction() == SELECTION_ADD) { useCursor(KisCursor::load("tool_outline_selection_cursor_add.png", 6, 6)); } else if (selectionAction() == SELECTION_SUBTRACT) { useCursor(KisCursor::load("tool_outline_selection_cursor_sub.png", 6, 6)); } else { KisToolSelect::resetCursorStyle(); } } - diff --git a/plugins/tools/selectiontools/KisToolSelectMagnetic.h b/plugins/tools/selectiontools/KisToolSelectMagnetic.h index 965de0996d..b10e457ed4 100644 --- a/plugins/tools/selectiontools/KisToolSelectMagnetic.h +++ b/plugins/tools/selectiontools/KisToolSelectMagnetic.h @@ -1,103 +1,103 @@ /* * Copyright (c) 2019 Kuntal Majumder * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_SELECT_MAGNETIC_H_ #define KIS_TOOL_SELECT_MAGNETIC_H_ #include #include "KisSelectionToolFactoryBase.h" #include #include #include "KisMagneticWorker.h" class QPainterPath; class KisToolSelectMagnetic : public KisToolSelect { Q_OBJECT public: KisToolSelectMagnetic(KoCanvasBase *canvas); ~KisToolSelectMagnetic() override = default; void beginPrimaryAction(KoPointerEvent *event) override; void continuePrimaryAction(KoPointerEvent *event) override; void endPrimaryAction(KoPointerEvent *event) override; void paint(QPainter& gc, const KoViewConverter &converter) override; void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; void mouseMoveEvent(KoPointerEvent *event) override; void resetCursorStyle() override; void requestStrokeEnd() override; void requestStrokeCancellation() override; - QWidget* createOptionWidget() override; + QWidget * createOptionWidget() override; public Q_SLOTS: void deactivate() override; - void activate(KoToolBase::ToolActivation activation, const QSet &shapes) override; + void activate(KoToolBase::ToolActivation activation, const QSet &shapes) override; void requestUndoDuringStroke() override; void slotSetRadius(int); void slotSetThreshold(int); protected: using KisToolSelectBase::m_widgetHelper; private: void finishSelectionAction(); void updateFeedback(); void updateContinuedMode(); void updateCanvas(); QPainterPath m_paintPath; QVector m_points; QVector m_anchorPoints; bool m_continuedMode; QPointF m_lastCursorPos; QPoint m_lastAnchor; bool m_complete; KisMagneticWorker m_worker; int m_radius, m_threshold, m_checkPoint; QRectF m_snapBound; KConfigGroup m_configGroup; }; class KisToolSelectMagneticFactory : public KisSelectionToolFactoryBase { public: KisToolSelectMagneticFactory() : KisSelectionToolFactoryBase("KisToolSelectMagnetic") { setToolTip(i18n("Magnetic Selection Tool")); setSection(TOOL_TYPE_SELECTION); setIconName(koIconNameCStr("tool_magnetic_selection")); setPriority(8); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); } - ~KisToolSelectMagneticFactory() override {} + ~KisToolSelectMagneticFactory() override { } - KoToolBase * createTool(KoCanvasBase *canvas) override { + KoToolBase * createTool(KoCanvasBase *canvas) override + { return new KisToolSelectMagnetic(canvas); } }; -#endif //__selecttoolmagnetic_h__ - +#endif // __selecttoolmagnetic_h__