From 20d9443dbc42b3fe24260f2c4df77cca4d6591b8 Mon Sep 17 00:00:00 2001 From: Camille Ordronneau <camille.ordronneau@inria.fr> Date: Thu, 30 May 2024 17:08:59 +0200 Subject: [PATCH 1/5] Move part of hpp code to a cpp file --- src/CMakeLists.txt | 1 + src/trace/DrawTrace.cpp | 351 +++++++++++++++++++++++++++++++++++++++ src/trace/DrawTrace.hpp | 357 ++-------------------------------------- 3 files changed, 364 insertions(+), 345 deletions(-) create mode 100644 src/trace/DrawTrace.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 237969bb..601185cf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -158,6 +158,7 @@ set(VITE_SRCS trace/tree/Interval.cpp trace/Container.cpp trace/ContainerType.cpp + trace/DrawTrace.cpp trace/Entity.cpp trace/EntityType.cpp trace/EntityValue.cpp diff --git a/src/trace/DrawTrace.cpp b/src/trace/DrawTrace.cpp new file mode 100644 index 00000000..00bb56ab --- /dev/null +++ b/src/trace/DrawTrace.cpp @@ -0,0 +1,351 @@ +/* + ** This file is part of the ViTE project. + ** + ** This software is governed by the CeCILL-A license under French law + ** and abiding by the rules of distribution of free software. You can + ** use, modify and/or redistribute the software under the terms of the + ** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following + ** URL: "http://www.cecill.info". + ** + ** As a counterpart to the access to the source code and rights to copy, + ** modify and redistribute granted by the license, users are provided + ** only with a limited warranty and the software's author, the holder of + ** the economic rights, and the successive licensors have only limited + ** liability. + ** + ** In this respect, the user's attention is drawn to the risks associated + ** with loading, using, modifying and/or developing or reproducing the + ** software by the user in light of its specific status of free software, + ** that may mean that it is complicated to manipulate, and that also + ** therefore means that it is reserved for developers and experienced + ** professionals having in-depth computer knowledge. Users are therefore + ** encouraged to load and test the software's suitability as regards + ** their requirements in conditions enabling the security of their + ** systems and/or data to be ensured and, more generally, to use and + ** operate it in the same conditions as regards security. + ** + ** The fact that you are presently reading this means that you have had + ** knowledge of the CeCILL-A license and that you accept its terms. + ** + ** + ** ViTE developers are (for version 0.* to 1.0): + ** + ** - COULOMB Kevin + ** - FAVERGE Mathieu + ** - JAZEIX Johnny + ** - LAGRASSE Olivier + ** - MARCOUEILLE Jule + ** - NOISETTE Pascal + ** - REDONDY Arthur + ** - VUCHENER Clément + ** + */ +#include <iostream> +#include <cassert> +#include <cmath> +#include <map> +#include <vector> +/* -- */ +#include <QObject> +/* -- */ +#include "common/common.hpp" +#include "common/Message.hpp" +#include "common/Info.hpp" +/* -- */ +#include "trace/values/Values.hpp" +/* -- */ +#include "trace/tree/Interval.hpp" +#include "trace/tree/Node.hpp" +#include "trace/tree/BinaryTree.hpp" +/* -- */ +#include "trace/EntityTypes.hpp" +#include "trace/Entitys.hpp" +#include "trace/EntityValue.hpp" +#include "trace/Trace.hpp" +#include "trace/DrawTree.hpp" +// #include "trace/values/Value.hpp" +#include "trace/DrawTrace.hpp" + +DrawTrace::DrawTrace() { + _container_width = _DRAWING_CONTAINER_WIDTH_DEFAULT; + _container_height = _DRAWING_CONTAINER_HEIGHT_DEFAULT; + _container_h_space = _DRAWING_CONTAINER_H_SPACE_DEFAULT; + _container_v_space = _DRAWING_CONTAINER_V_SPACE_DEFAULT; + + _state_height = _DRAWING_STATE_HEIGHT_DEFAULT; + _state_v_space = _DRAWING_STATE_V_SPACE_DEFAULT; +} + +DrawTrace::~DrawTrace() = default; + +void DrawTrace::display_information(const Trace *trace, double x, double y, double d) { + const Container *container = nullptr; + const Container *ancestor = nullptr; + const Link *link; + const Event *event; + const State *state; + const Variable *variable; + + // find container needs to know the position of each container + Element_pos yr = y; + const Container::Vector *root_containers = trace->get_view_root_containers(); + if (root_containers->empty()) + root_containers = trace->get_root_containers(); + if (!root_containers->empty()) + for (const auto &root_container: *root_containers) + if ((container = search_container_by_position(root_container, yr))) + break; + + // If the clic is out + if (!container) + return; + + // Calculate the container positions + int position = 0; + for (const auto &root_container: *root_containers) + position += calc_container_positions(root_container, position); + + // First we browse to find a communication + ancestor = container; + if (!Info::Render::_no_arrows) { + + while (ancestor) { + if ((link = get_link(ancestor, x, y, d))) { + *Message::get_instance() << "<center><strong>Link</strong></center>" + << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" + << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" + << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" + << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; + print_extra_fields("Link", link->get_extra_fields()); + print_extra_fields("Value", link->get_value()->get_extra_fields()); + print_extra_fields("Type", link->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; + return; + } + else + ancestor = ancestor->get_parent(); + } + + // if not found, the link may hav been assigned to the first root container. + if ((link = get_link(root_containers->front(), x, y, d))) { + *Message::get_instance() << "<center><strong>Link</strong></center>" + << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" + << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" + << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" + << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; + print_extra_fields("Link", link->get_extra_fields()); + print_extra_fields("Value", link->get_value()->get_extra_fields()); + print_extra_fields("Type", link->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; + return; + } + } + // Now browsing for the events of the container root + // Verification if it is a clic on an event +#ifndef USE_ITC + if ((!container->get_events()->empty() || !container->get_states()->empty()) && yr < _container_height + _container_v_space) { +#else + if (((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) && yr < _container_height + _container_v_space) { +#endif + if (!Info::Render::_no_events) + if ((event = find_event(container, x, d))) { + *Message::get_instance() << "<center><strong>Event</strong></center>" + << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />" + << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />"; + print_extra_fields("Event", event->get_extra_fields()); + print_extra_fields("Value", event->get_value()->get_extra_fields()); + print_extra_fields("Type", event->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; + return; + } + if ((state = find_state(container, x))) { + *Message::get_instance() << "<center><strong>State</strong></center>" + << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />" + << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />" + << "<strong>Duration:</strong> " << state->get_duration() << "<br />"; + print_extra_fields("State", state->get_extra_fields()); + print_extra_fields("Value", state->get_value()->get_extra_fields()); + print_extra_fields("Type", state->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; + return; + } + } + else { +#ifdef USE_ITC + if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) +#else + if (!container->get_events()->empty() || !container->get_states()->empty()) +#endif + yr -= _container_height + _container_v_space; + const std::map<VariableType *, Variable *> *variable_map = container->get_variables(); + std::map<VariableType *, Variable *>::const_iterator i = variable_map->begin(); + while (yr > _container_height + _container_v_space) { + yr -= _container_height + _container_v_space; + i++; + } + if (i != variable_map->end()) { + variable = (*i).second; + *Message::get_instance() << "<center><strong>Variable</strong></center>" + << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />" + << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" + << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" + << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />" + << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />"; + print_extra_fields("Type", variable->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; + + return; + } + } + + *Message::get_instance() << Message::endsi; + // Nothing has been found + return; +} + +void DrawTrace::print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) { + if (extra_fields != nullptr && !extra_fields->empty()) { + *Message::get_instance() << "<em>" << name << " extra fields</em><br />"; + for (const auto &extra_field: *extra_fields) + *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />"; + } +} + +const Container *DrawTrace::search_container_by_position(const Container *container, Element_pos &y) { + const Container *result; + // Search if the result is a descendant + const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed + if (children->empty()) + children = container->get_children(); + for (const auto &i: *children) { + if ((result = search_container_by_position(i, y)) != nullptr) + return result; + } + + // Calculate the size of the container (without its children) + int size = 0; +#ifdef USE_ITC + if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) +#else + if (!container->get_states()->empty() || !container->get_events()->empty()) +#endif + size++; + if (container->get_variable_number() > 0) + size += container->get_variable_number(); + + if (children->empty() && size < 1) // Minimum size + size = 1; + + // Test if the position is in this container + if (y < size * (_container_height + _container_v_space)) + return container; + else + y -= size * (_container_height + _container_v_space); + + // The position is outside this container + return nullptr; +} + +int DrawTrace::calc_container_positions(const Container *container, int position) { + int size = 0; + + // Draw children + const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed + if (children->empty()) + children = container->get_children(); + for (const auto &i: *children) { + size += calc_container_positions(i, position + size); + } + + // Store the position to draw links + _container_positions[container] = position; // First line after children + _container_sizes[container] = size; // First line after children + + // Use one line for states and events +#ifdef USE_ITC + if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) { +#else + if (!container->get_states()->empty() || !container->get_events()->empty()) { +#endif + size++; + } + + // Use one line for each variable + if (container->get_variable_number() > 0) { + size += container->get_variable_number(); + } + + return size; +} + +const State *DrawTrace::find_state(const Container *container, Element_pos x) { + if (!container || container->get_states() == nullptr) + return nullptr; + + Node<StateChange> *node = container->get_states()->get_root(); + + while (node) { + Element_pos t = node->get_element()->get_time().get_value(); + if (x < t) { + if (node->get_element()->get_left_state() && node->get_element()->get_left_state()->get_start_time().get_value() < x) + return node->get_element()->get_left_state(); + node = node->get_left_child(); + } + else { + if (node->get_element()->get_right_state() && x < node->get_element()->get_right_state()->get_end_time().get_value()) + return node->get_element()->get_right_state(); + node = node->get_right_child(); + } + } + + return nullptr; +} + +bool DrawTrace::link_is_in_set(Link *link, std::vector<const Container *> *set_container, Interval *interval) { + const Container *src = link->get_source(); + const Container *dest = link->get_destination(); + for (unsigned int i = 0; i < set_container->size(); i++) { + if (src == (*set_container)[i]) { + for (const auto &j: *set_container) + if (dest == j) + if ( + (interval->_left.get_value() < link->get_start_time().get_value() && interval->_right.get_value() > link->get_end_time().get_value()) || (interval->_left.get_value() < link->get_end_time().get_value() && interval->_right.get_value() > link->get_start_time().get_value())) + return true; + } + } + return false; +} + +bool DrawTrace::is_in_set(const Container *c, std::vector<const Container *> *set_container) { + if (!c || !set_container) + return false; + for (const auto &i: *set_container) + if (c == i) + return true; + return false; +} + +void DrawTrace::add(std::vector<const Container *> *container, std::stack<Container *> *containers) { + + while (!containers->empty()) { + const Container *c = containers->top(); + containers->pop(); + const Container::Vector *children = c->get_view_children(); // we want to display only children meant to be displayed + if (children->empty()) + children = c->get_children(); + for (const auto &i: *children) { + containers->push(i); + container->push_back(i); + } + add(container, containers); + } +} diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp index bf4f481e..e25ab09a 100644 --- a/src/trace/DrawTrace.hpp +++ b/src/trace/DrawTrace.hpp @@ -47,10 +47,6 @@ #ifndef DRAW_TRACE_HPP #define DRAW_TRACE_HPP -#include <iostream> -#include <cassert> -#include <cmath> - /* * Theses constants can not be put as static const float because it is a template and there binary representation is not normed by the C++ langage. */ @@ -154,20 +150,12 @@ public: /*! * \brief The default constructor */ - DrawTrace() { - _container_width = _DRAWING_CONTAINER_WIDTH_DEFAULT; - _container_height = _DRAWING_CONTAINER_HEIGHT_DEFAULT; - _container_h_space = _DRAWING_CONTAINER_H_SPACE_DEFAULT; - _container_v_space = _DRAWING_CONTAINER_V_SPACE_DEFAULT; - - _state_height = _DRAWING_STATE_HEIGHT_DEFAULT; - _state_v_space = _DRAWING_STATE_V_SPACE_DEFAULT; - } + DrawTrace(); /*! * \brief The destructor */ - virtual ~DrawTrace() = default; + virtual ~DrawTrace(); /*********************************** * @@ -585,354 +573,33 @@ public: /* * \brief Assuming someone has clicked in (x, y), display the description corresponding to the item clicked */ - void display_information(const Trace *trace, double x, double y, double d) { - const Container *container = nullptr; - const Container *ancestor = nullptr; - const Link *link; - const Event *event; - const State *state; - const Variable *variable; - - // find container needs to know the position of each container - Element_pos yr = y; - const Container::Vector *root_containers = trace->get_view_root_containers(); - if (root_containers->empty()) - root_containers = trace->get_root_containers(); - if (!root_containers->empty()) - for (const auto &root_container: *root_containers) - if ((container = search_container_by_position(root_container, yr))) - break; - - // If the clic is out - if (!container) - return; - - // Calculate the container positions - int position = 0; - for (const auto &root_container: *root_containers) - position += calc_container_positions(root_container, position); - - // First we browse to find a communication - ancestor = container; - if (!Info::Render::_no_arrows) { - - while (ancestor) { - if ((link = get_link(ancestor, x, y, d))) { - *Message::get_instance() << "<center><strong>Link</strong></center>" - << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" - << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" - << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" - << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; - print_extra_fields("Link", link->get_extra_fields()); - print_extra_fields("Value", link->get_value()->get_extra_fields()); - print_extra_fields("Type", link->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; - return; - } - else - ancestor = ancestor->get_parent(); - } - - // if not found, the link may hav been assigned to the first root container. - if ((link = get_link(root_containers->front(), x, y, d))) { - *Message::get_instance() << "<center><strong>Link</strong></center>" - << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" - << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" - << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" - << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; - print_extra_fields("Link", link->get_extra_fields()); - print_extra_fields("Value", link->get_value()->get_extra_fields()); - print_extra_fields("Type", link->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; - return; - } - } - // Now browsing for the events of the container root - // Verification if it is a clic on an event -#ifndef USE_ITC - if ((!container->get_events()->empty() || !container->get_states()->empty()) && yr < _container_height + _container_v_space) { -#else - if (((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) && yr < _container_height + _container_v_space) { -#endif - if (!Info::Render::_no_events) - if ((event = find_event(container, x, d))) { - *Message::get_instance() << "<center><strong>Event</strong></center>" - << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />" - << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />"; - print_extra_fields("Event", event->get_extra_fields()); - print_extra_fields("Value", event->get_value()->get_extra_fields()); - print_extra_fields("Type", event->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; - return; - } - if ((state = find_state(container, x))) { - *Message::get_instance() << "<center><strong>State</strong></center>" - << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />" - << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />" - << "<strong>Duration:</strong> " << state->get_duration() << "<br />"; - print_extra_fields("State", state->get_extra_fields()); - print_extra_fields("Value", state->get_value()->get_extra_fields()); - print_extra_fields("Type", state->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; - return; - } - } - else { -#ifdef USE_ITC - if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) -#else - if (!container->get_events()->empty() || !container->get_states()->empty()) -#endif - yr -= _container_height + _container_v_space; - const std::map<VariableType *, Variable *> *variable_map = container->get_variables(); - std::map<VariableType *, Variable *>::const_iterator i = variable_map->begin(); - while (yr > _container_height + _container_v_space) { - yr -= _container_height + _container_v_space; - i++; - } - if (i != variable_map->end()) { - variable = (*i).second; - *Message::get_instance() << "<center><strong>Variable</strong></center>" - << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />" - << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" - << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" - << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />" - << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />"; - print_extra_fields("Type", variable->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; - - return; - } - } - - *Message::get_instance() << Message::endsi; - // Nothing has been found - return; - } - - void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) { - if (extra_fields != nullptr && !extra_fields->empty()) { - *Message::get_instance() << "<em>" << name << " extra fields</em><br />"; - for (const auto &extra_field: *extra_fields) - *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />"; - } - } - - const Container *search_container_by_position(const Container *container, Element_pos &y) { - const Container *result; - // Search if the result is a descendant - const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed - if (children->empty()) - children = container->get_children(); - for (const auto &i: *children) { - if ((result = search_container_by_position(i, y)) != nullptr) - return result; - } - - // Calculate the size of the container (without its children) - int size = 0; -#ifdef USE_ITC - if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) -#else - if (!container->get_states()->empty() || !container->get_events()->empty()) -#endif - size++; - if (container->get_variable_number() > 0) - size += container->get_variable_number(); + void display_information(const Trace *trace, double x, double y, double d); - if (children->empty() && size < 1) // Minimum size - size = 1; + void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields); - // Test if the position is in this container - if (y < size * (_container_height + _container_v_space)) - return container; - else - y -= size * (_container_height + _container_v_space); - - // The position is outside this container - return nullptr; - } + const Container *search_container_by_position(const Container *container, Element_pos &y); /* * \fn browse_container(T* draw_object, const Container *container, int position, int depth) * \brief Recursive function that browse a container to draw it with a T painting object in position, knowing the current depth in the tree */ - int calc_container_positions(const Container *container, int position) { - int size = 0; - - // Draw children - const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed - if (children->empty()) - children = container->get_children(); - for (const auto &i: *children) { - size += calc_container_positions(i, position + size); - } - - // Store the position to draw links - _container_positions[container] = position; // First line after children - _container_sizes[container] = size; // First line after children - - // Use one line for states and events -#ifdef USE_ITC - if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) { -#else - if (!container->get_states()->empty() || !container->get_events()->empty()) { -#endif - size++; - } - - // Use one line for each variable - if (container->get_variable_number() > 0) { - size += container->get_variable_number(); - } - - return size; - } + int calc_container_positions(const Container *container, int position); /*! - * \brief Tries to find a link passing by x and y in the container - */ - const Link *get_link(const Container *container, Element_pos x, Element_pos y, Element_pos d) { - const Link::Vector *link_list; - Link *link; - double a, b, c; // Equation: ax + by + c = 0 - double x1, x2, y1, y2; - - if (!container) - return nullptr; - - // Browse links - link_list = container->get_links(); - for (const auto &it: *link_list) { - - link = it; - - double srcpos = _container_positions[link->get_source()]; - double dstpos = _container_positions[link->get_destination()]; - double srcsize = _container_sizes[link->get_source()]; - double dstsize = _container_sizes[link->get_destination()]; - - x1 = link->get_start_time().get_value(); - x2 = link->get_end_time().get_value(); - - y1 = (srcpos + 0.5 * srcsize) * (_container_height + _container_v_space); - y2 = (dstpos + 0.5 * dstsize) * (_container_height + _container_v_space); - - if (((x1 - d <= x && x <= x2 + d) || (x2 - d <= x && x <= x1 + d)) && ((y1 - d <= y && y <= y2 + d) || (y2 - d <= y && y <= y1 + d))) { // Test the interval - a = y1 - y2; - b = x2 - x1; - c = -(a * x1 + b * y1); - - double e = a * x + b * y + c; - - if (e * e / (a * a + b * b) < d * d) // Test the distance - return link; - } - } - - return nullptr; - } - - /* - * \brief Returns the event that occurs at the time x in the container + * \brief Tries to find all links passing by x and y in the container */ - const Event *find_event(const Container *container, Element_pos x, Element_pos d) { - if (!container || container->get_events() == nullptr) - return nullptr; - - Node<Event> *node = container->get_events()->get_root(); - - while (node) { - Element_pos t = node->get_element()->get_time().get_value(); - if (x < t) { - if (t - x < d) - return node->get_element(); - node = node->get_left_child(); - } - else { - if (x - t < d) - return node->get_element(); - node = node->get_right_child(); - } - } - - return nullptr; - } + const Event *find_event(const Container *container, Element_pos x, Element_pos d); /* * \brief Returns the state at the time x */ - const State *find_state(const Container *container, Element_pos x) { - if (!container || container->get_states() == nullptr) - return nullptr; - - Node<StateChange> *node = container->get_states()->get_root(); - - while (node) { - Element_pos t = node->get_element()->get_time().get_value(); - if (x < t) { - if (node->get_element()->get_left_state() && node->get_element()->get_left_state()->get_start_time().get_value() < x) - return node->get_element()->get_left_state(); - node = node->get_left_child(); - } - else { - if (node->get_element()->get_right_state() && x < node->get_element()->get_right_state()->get_end_time().get_value()) - return node->get_element()->get_right_state(); - node = node->get_right_child(); - } - } + const State *find_state(const Container *container, Element_pos x); - return nullptr; - } - - bool link_is_in_set(Link *link, std::vector<const Container *> *set_container, Interval *interval) { - const Container *src = link->get_source(); - const Container *dest = link->get_destination(); - for (unsigned int i = 0; i < set_container->size(); i++) { - if (src == (*set_container)[i]) { - for (const auto &j: *set_container) - if (dest == j) - if ( - (interval->_left.get_value() < link->get_start_time().get_value() && interval->_right.get_value() > link->get_end_time().get_value()) || (interval->_left.get_value() < link->get_end_time().get_value() && interval->_right.get_value() > link->get_start_time().get_value())) - return true; - } - } - return false; - } + bool link_is_in_set(Link *link, std::vector<const Container *> *set_container, Interval *interval); - bool is_in_set(const Container *c, std::vector<const Container *> *set_container) { - if (!c || !set_container) - return false; - for (const auto &i: *set_container) - if (c == i) - return true; - return false; - } + bool is_in_set(const Container *c, std::vector<const Container *> *set_container); - void add(std::vector<const Container *> *container, std::stack<Container *> *containers) { - - while (!containers->empty()) { - const Container *c = containers->top(); - containers->pop(); - const Container::Vector *children = c->get_view_children(); // we want to display only children meant to be displayed - if (children->empty()) - children = c->get_children(); - for (const auto &i: *children) { - containers->push(i); - container->push_back(i); - } - add(container, containers); - } - } + void add(std::vector<const Container *> *container, std::stack<Container *> *containers); template <class T> void draw_text_variable_values(T *render, std::map<long int, double> *var_map, double date) { -- GitLab From 067e3a49f2da702b9b0ab22c9f13cd4046d96de8 Mon Sep 17 00:00:00 2001 From: Ordronneau Camille <camille.ordronneau@inria.fr> Date: Thu, 23 May 2024 16:43:20 +0200 Subject: [PATCH 2/5] Add functions for clearer code --- src/trace/DrawTrace.cpp | 123 +++++++++++++++++++++------------------- src/trace/DrawTrace.hpp | 2 - 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/src/trace/DrawTrace.cpp b/src/trace/DrawTrace.cpp index 00bb56ab..02951e3f 100644 --- a/src/trace/DrawTrace.cpp +++ b/src/trace/DrawTrace.cpp @@ -78,6 +78,65 @@ DrawTrace::DrawTrace() { DrawTrace::~DrawTrace() = default; +void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) { + if (extra_fields != nullptr && !extra_fields->empty()) { + *Message::get_instance() << "<em>" << name << " extra fields</em><br />"; + for (const auto &extra_field: *extra_fields) + *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />"; + } +} + +void display_link_info(const Link *link) { + *Message::get_instance() << "<center><strong>Link</strong></center>" + << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" + << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" + << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" + << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; + print_extra_fields("Link", link->get_extra_fields()); + print_extra_fields("Value", link->get_value()->get_extra_fields()); + print_extra_fields("Type", link->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; +} + +void display_event_info(const Event *event) { + *Message::get_instance() << "<center><strong>Event</strong></center>" + << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />" + << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />"; + print_extra_fields("Event", event->get_extra_fields()); + print_extra_fields("Value", event->get_value()->get_extra_fields()); + print_extra_fields("Type", event->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; +} + +void display_state_info(const State *state) { + *Message::get_instance() << "<center><strong>State</strong></center>" + << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />" + << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />" + << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />" + << "<strong>Duration:</strong> " << state->get_duration() << "<br />"; + print_extra_fields("State", state->get_extra_fields()); + print_extra_fields("Value", state->get_value()->get_extra_fields()); + print_extra_fields("Type", state->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; +} + +void display_variable_info(const Variable *variable, const double &x) { + *Message::get_instance() << "<center><strong>Variable</strong></center>" + << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />" + << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />" + << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" + << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" + << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />" + << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />"; + print_extra_fields("Type", variable->get_type()->get_extra_fields()); + *Message::get_instance() << Message::endsi; +} + void DrawTrace::display_information(const Trace *trace, double x, double y, double d) { const Container *container = nullptr; const Container *ancestor = nullptr; @@ -111,17 +170,7 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub while (ancestor) { if ((link = get_link(ancestor, x, y, d))) { - *Message::get_instance() << "<center><strong>Link</strong></center>" - << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" - << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" - << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" - << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; - print_extra_fields("Link", link->get_extra_fields()); - print_extra_fields("Value", link->get_value()->get_extra_fields()); - print_extra_fields("Type", link->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; + display_link_info(link); return; } else @@ -130,17 +179,7 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub // if not found, the link may hav been assigned to the first root container. if ((link = get_link(root_containers->front(), x, y, d))) { - *Message::get_instance() << "<center><strong>Link</strong></center>" - << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />" - << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />" - << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />" - << "<strong>Duration:</strong> " << link->get_duration() << "<br />"; - print_extra_fields("Link", link->get_extra_fields()); - print_extra_fields("Value", link->get_value()->get_extra_fields()); - print_extra_fields("Type", link->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; + display_link_info(link); return; } } @@ -153,28 +192,11 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub #endif if (!Info::Render::_no_events) if ((event = find_event(container, x, d))) { - *Message::get_instance() << "<center><strong>Event</strong></center>" - << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />" - << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />"; - print_extra_fields("Event", event->get_extra_fields()); - print_extra_fields("Value", event->get_value()->get_extra_fields()); - print_extra_fields("Type", event->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; + display_event_info(event); return; } if ((state = find_state(container, x))) { - *Message::get_instance() << "<center><strong>State</strong></center>" - << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />" - << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />" - << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />" - << "<strong>Duration:</strong> " << state->get_duration() << "<br />"; - print_extra_fields("State", state->get_extra_fields()); - print_extra_fields("Value", state->get_value()->get_extra_fields()); - print_extra_fields("Type", state->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; + display_state_info(state); return; } } @@ -193,16 +215,7 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub } if (i != variable_map->end()) { variable = (*i).second; - *Message::get_instance() << "<center><strong>Variable</strong></center>" - << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />" - << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />" - << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" - << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />" - << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />" - << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />"; - print_extra_fields("Type", variable->get_type()->get_extra_fields()); - *Message::get_instance() << Message::endsi; - + display_variable_info(variable, x); return; } } @@ -212,14 +225,6 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub return; } -void DrawTrace::print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) { - if (extra_fields != nullptr && !extra_fields->empty()) { - *Message::get_instance() << "<em>" << name << " extra fields</em><br />"; - for (const auto &extra_field: *extra_fields) - *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />"; - } -} - const Container *DrawTrace::search_container_by_position(const Container *container, Element_pos &y) { const Container *result; // Search if the result is a descendant diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp index e25ab09a..580bd1a9 100644 --- a/src/trace/DrawTrace.hpp +++ b/src/trace/DrawTrace.hpp @@ -575,8 +575,6 @@ public: */ void display_information(const Trace *trace, double x, double y, double d); - void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields); - const Container *search_container_by_position(const Container *container, Element_pos &y); /* -- GitLab From 126f068d8a5c8aec4f09366e37081aa72731caff Mon Sep 17 00:00:00 2001 From: Ordronneau Camille <camille.ordronneau@inria.fr> Date: Tue, 28 May 2024 10:32:50 +0200 Subject: [PATCH 3/5] Add getting all Entities when double clicking --- src/trace/DrawTrace.cpp | 116 ++++++++++++++++++++++++++++++++-------- src/trace/DrawTrace.hpp | 2 +- 2 files changed, 96 insertions(+), 22 deletions(-) diff --git a/src/trace/DrawTrace.cpp b/src/trace/DrawTrace.cpp index 02951e3f..73ccf9c9 100644 --- a/src/trace/DrawTrace.cpp +++ b/src/trace/DrawTrace.cpp @@ -52,6 +52,8 @@ #include "common/Message.hpp" #include "common/Info.hpp" /* -- */ +#include "interface/Interface.hpp" +/* -- */ #include "trace/values/Values.hpp" /* -- */ #include "trace/tree/Interval.hpp" @@ -137,11 +139,80 @@ void display_variable_info(const Variable *variable, const double &x) { *Message::get_instance() << Message::endsi; } +void DrawTrace::fill_link_list(const Container *container, const Element_pos &x, const Element_pos &y, const Element_pos &accuracy, Link::Vector *link_list) { + const Link::Vector *container_links; + Link *link; + double a, b, c; // Equation: ax + by + c = 0 + double x1, x2, y1, y2; + + if (!container) + return; + + // Browse links + container_links = container->get_links(); + for (const auto &it: *container_links) { + link = it; + + double srcpos = _container_positions[link->get_source()]; + double dstpos = _container_positions[link->get_destination()]; + double srcsize = _container_sizes[link->get_source()]; + double dstsize = _container_sizes[link->get_destination()]; + + x1 = link->get_start_time().get_value(); + x2 = link->get_end_time().get_value(); + + y1 = (srcpos + 0.5 * srcsize) * (_container_height + _container_v_space); + y2 = (dstpos + 0.5 * dstsize) * (_container_height + _container_v_space); + + // Test if (x, y) is in the counding box made by the link ends + if (((x1 - accuracy <= x && x <= x2 + accuracy) || (x2 - accuracy <= x && x <= x1 + accuracy)) && ((y1 - accuracy <= y && y <= y2 + accuracy) || (y2 - accuracy <= y && y <= y1 + accuracy))) { + a = y1 - y2; + b = x2 - x1; + c = -(a * x1 + b * y1); + + double e = a * x + b * y + c; + + // Test the distance from (x, y) to the link + if (e * e / (a * a + b * b) < accuracy) { + link_list->push_back(link); + } + } + } + + return; +} + +void fill_event_list(const Node<Event> *node, const Element_pos &x, const Element_pos &d, std::list<const Event *> *event_list) { + + if (nullptr == node) { + return; + } + + const Element_pos t = node->get_element()->get_time().get_value(); + + if (t < x) { + if (x - t < d) { + fill_event_list(node->get_left_child(), x, d, event_list); + event_list->push_back(node->get_element()); + } + fill_event_list(node->get_right_child(), x, d, event_list); + return; + } + + fill_event_list(node->get_left_child(), x, d, event_list); + if (t - x < d) { + event_list->push_back(node->get_element()); + fill_event_list(node->get_right_child(), x, d, event_list); + } + return; +} + void DrawTrace::display_information(const Trace *trace, double x, double y, double d) { const Container *container = nullptr; const Container *ancestor = nullptr; - const Link *link; - const Event *event; + + Link::Vector link_list; + std::list<const Event *> event_list; const State *state; const Variable *variable; @@ -166,21 +237,19 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub // First we browse to find a communication ancestor = container; - if (!Info::Render::_no_arrows) { + Message::get_interface()->selection_information_clear(); + if (!Info::Render::_no_arrows) { while (ancestor) { - if ((link = get_link(ancestor, x, y, d))) { - display_link_info(link); - return; - } - else - ancestor = ancestor->get_parent(); + fill_link_list(ancestor, x, y, d, &link_list); + ancestor = ancestor->get_parent(); } - - // if not found, the link may hav been assigned to the first root container. - if ((link = get_link(root_containers->front(), x, y, d))) { + fill_link_list(root_containers->front(), x, y, d, &link_list); + int i = 1; + for (auto const &link: link_list) { + Message::get_interface()->selection_information_new_tab("Link " + std::to_string(i)); display_link_info(link); - return; + i++; } } // Now browsing for the events of the container root @@ -190,14 +259,20 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub #else if (((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) && yr < _container_height + _container_v_space) { #endif - if (!Info::Render::_no_events) - if ((event = find_event(container, x, d))) { - display_event_info(event); - return; + if (!Info::Render::_no_events) { + if (container->get_events() != nullptr) { + fill_event_list(container->get_events()->get_root(), x, d, &event_list); + int i = 1; + for (auto const &event: event_list) { + Message::get_interface()->selection_information_new_tab("Event " + std::to_string(i)); + display_event_info(event); + i++; + } } + } if ((state = find_state(container, x))) { + Message::get_interface()->selection_information_new_tab("State"); display_state_info(state); - return; } } else { @@ -215,12 +290,11 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub } if (i != variable_map->end()) { variable = (*i).second; + Message::get_interface()->selection_information_new_tab("Variable"); display_variable_info(variable, x); - return; } } - - *Message::get_instance() << Message::endsi; + Message::get_interface()->selection_information_show(); // Nothing has been found return; } diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp index 580bd1a9..44a1f0ee 100644 --- a/src/trace/DrawTrace.hpp +++ b/src/trace/DrawTrace.hpp @@ -586,7 +586,7 @@ public: /*! * \brief Tries to find all links passing by x and y in the container */ - const Event *find_event(const Container *container, Element_pos x, Element_pos d); + void fill_link_list(const Container *container, const Element_pos &x, const Element_pos &y, const Element_pos &d, Link::Vector *link_list); /* * \brief Returns the state at the time x -- GitLab From acc0d109880aa82183a2c5ba4b591c1b52bd92d8 Mon Sep 17 00:00:00 2001 From: Ordronneau Camille <camille.ordronneau@inria.fr> Date: Fri, 24 May 2024 16:49:43 +0200 Subject: [PATCH 4/5] Change information window ui, textEdit became QTabWidget --- src/interface/info_window.ui | 114 ++++++++++++++--------------------- 1 file changed, 46 insertions(+), 68 deletions(-) diff --git a/src/interface/info_window.ui b/src/interface/info_window.ui index 032e20b9..ae159c4c 100644 --- a/src/interface/info_window.ui +++ b/src/interface/info_window.ui @@ -1,7 +1,8 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>info_window</class> - <widget class="QMainWindow" name="info_window" > - <property name="geometry" > + <widget class="QMainWindow" name="info_window"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> @@ -9,53 +10,56 @@ <height>229</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>Informations</string> </property> - <property name="windowIcon" > - <iconset resource="vite.qrc" > + <property name="windowIcon"> + <iconset resource="vite.qrc"> <normaloff>:/icon/icon/vite.png</normaloff>:/icon/icon/vite.png</iconset> </property> - <widget class="QWidget" name="centralwidget" > - <layout class="QHBoxLayout" name="horizontalLayout_2" > + <widget class="QWidget" name="centralwidget"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <layout class="QHBoxLayout" name="horizontalLayout" > - <property name="rightMargin" > + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="rightMargin"> <number>0</number> </property> - <property name="bottomMargin" > + <property name="bottomMargin"> <number>0</number> </property> <item> - <layout class="QVBoxLayout" name="verticalLayout_3" > - <property name="rightMargin" > + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="rightMargin"> <number>0</number> </property> <item> - <widget class="QGroupBox" name="info_trace" > - <property name="focusPolicy" > + <widget class="QGroupBox" name="info_trace"> + <property name="focusPolicy"> <enum>Qt::StrongFocus</enum> </property> - <property name="title" > + <property name="title"> <string>Trace Resume</string> </property> - <layout class="QHBoxLayout" name="horizontalLayout_3" > + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QTextEdit" name="info_trace_text" > - <property name="verticalScrollBarPolicy" > + <widget class="QTextEdit" name="info_trace_text"> + <property name="verticalScrollBarPolicy"> <enum>Qt::ScrollBarAsNeeded</enum> </property> - <property name="readOnly" > + <property name="readOnly"> <bool>true</bool> </property> - <property name="html" > - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> + <property name="html"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string> +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Ubuntu Sans'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html></string> </property> - <property name="textInteractionFlags" > + <property name="textInteractionFlags"> <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> </property> </widget> @@ -64,8 +68,8 @@ p, li { white-space: pre-wrap; } </widget> </item> <item> - <widget class="QPushButton" name="info_trace_clear" > - <property name="text" > + <widget class="QPushButton" name="info_trace_clear"> + <property name="text"> <string>clear trace resume</string> </property> </widget> @@ -73,33 +77,23 @@ p, li { white-space: pre-wrap; } </layout> </item> <item> - <layout class="QVBoxLayout" name="verticalLayout_4" > - <property name="rightMargin" > + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="rightMargin"> <number>0</number> </property> - <property name="bottomMargin" > + <property name="bottomMargin"> <number>0</number> </property> <item> - <widget class="QGroupBox" name="info_selection" > - <property name="title" > + <widget class="QGroupBox" name="info_selection"> + <property name="title"> <string>Selection Informations</string> </property> - <layout class="QHBoxLayout" name="horizontalLayout_4" > + <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <widget class="QTextEdit" name="info_selection_text" > - <property name="readOnly" > - <bool>true</bool> - </property> - <property name="html" > - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string> - </property> - <property name="textInteractionFlags" > - <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + <widget class="QTabWidget" name="info_selection_tab"> + <property name="currentIndex"> + <number>-1</number> </property> </widget> </item> @@ -107,8 +101,8 @@ p, li { white-space: pre-wrap; } </widget> </item> <item> - <widget class="QPushButton" name="pushButton" > - <property name="text" > + <widget class="QPushButton" name="pushButton"> + <property name="text"> <string>clear informations</string> </property> </widget> @@ -121,7 +115,7 @@ p, li { white-space: pre-wrap; } </widget> </widget> <resources> - <include location="vite.qrc" /> + <include location="vite.qrc"/> </resources> <connections> <connection> @@ -130,31 +124,15 @@ p, li { white-space: pre-wrap; } <receiver>info_trace_text</receiver> <slot>clear()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>47</x> <y>217</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>152</x> <y>120</y> </hint> </hints> </connection> - <connection> - <sender>pushButton</sender> - <signal>clicked()</signal> - <receiver>info_selection_text</receiver> - <slot>clear()</slot> - <hints> - <hint type="sourcelabel" > - <x>369</x> - <y>217</y> - </hint> - <hint type="destinationlabel" > - <x>372</x> - <y>164</y> - </hint> - </hints> - </connection> </connections> </ui> -- GitLab From 5de2883ed62fe974720b04bfd414b4af935f48f8 Mon Sep 17 00:00:00 2001 From: Ordronneau Camille <camille.ordronneau@inria.fr> Date: Fri, 24 May 2024 16:51:24 +0200 Subject: [PATCH 5/5] Change Interface.hpp interface --- src/core/Core.hpp | 15 +++++++++++ src/interface/Interface.hpp | 6 +++++ src/interface/Interface_graphic.cpp | 42 ++++++++++++++++++++++++----- src/interface/Interface_graphic.hpp | 14 +++++++++- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/core/Core.hpp b/src/core/Core.hpp index ce5a564b..4971b4cc 100644 --- a/src/core/Core.hpp +++ b/src/core/Core.hpp @@ -451,6 +451,21 @@ public: void selection_information(const std::string &) const override { } + /*! + * \brief Only use in graphic interface. + */ + void selection_information_clear() const override { } + + /*! + * \brief Only use in graphic interface. + */ + void selection_information_show() const override { } + + /*! + * \brief Only use in graphic interface. + */ + virtual void selection_information_new_tab(const std::string &) const override { } + /*! *\brief Set the minimum for export *\param d The double. diff --git a/src/interface/Interface.hpp b/src/interface/Interface.hpp index 05908b55..98a38026 100644 --- a/src/interface/Interface.hpp +++ b/src/interface/Interface.hpp @@ -76,6 +76,12 @@ public: */ virtual void information(const std::string &) const = 0; + virtual void selection_information_clear() const = 0; + + virtual void selection_information_show() const = 0; + + virtual void selection_information_new_tab(const std::string &) const = 0; + /*! *\arg string : the string to be displayed. *\brief The function takes strings and/or numbers then displayed it in the entity informative text area in the info window (use in graphic interface). diff --git a/src/interface/Interface_graphic.cpp b/src/interface/Interface_graphic.cpp index 1db14b05..6893fedf 100644 --- a/src/interface/Interface_graphic.cpp +++ b/src/interface/Interface_graphic.cpp @@ -52,6 +52,7 @@ #include <list> /* -- */ #include <QObject> +#include <QWidget> #include <QtUiTools>/* for the run-time loading .ui file */ #include <QCloseEvent> #include <QDir> @@ -219,7 +220,7 @@ void Interface_graphic::load_windows() { CKFP(_ui_fullscreen_menu = this->findChild<QAction *>(QStringLiteral("fullscreen")), "Cannot find the fullscreen menu in the .ui file"); CKFP(_ui_info_trace_text = _ui_info_window->findChild<QTextEdit *>(QStringLiteral("info_trace_text")), "Cannot find the info_trace_text QTextEdit widget in the .ui file"); - CKFP(_ui_info_selection_text = _ui_info_window->findChild<QTextEdit *>(QStringLiteral("info_selection_text")), "Cannot find the info_selection_text QTextEdit widget in the .ui file"); + CKFP(_ui_info_selection_tabs = _ui_info_window->findChild<QTabWidget *>(QStringLiteral("info_selection_tab")), "Cannot find the info_selection_tab QTabWidget widget in the .ui file"); CKFP(_ui_toolbar = this->findChild<QToolBar *>(QStringLiteral("toolBar")), "Cannot find the tool bar in the .ui file"); CKFP(_ui_x_scroll = this->findChild<QScrollBar *>(QStringLiteral("x_scroll")), "Cannot find the horizontal scroll bar in the .ui file"); @@ -304,15 +305,42 @@ void Interface_graphic::information(const string &s) const { * **********************************/ -void Interface_graphic::selection_information(const string &s) const { - QString buf = QString::fromStdString(s); - _ui_info_selection_text->clear(); /* Clear the current text (if exists) */ - _ui_info_selection_text->insertHtml(QStringLiteral("<font color='blue'>") + buf + QStringLiteral("</font>")); - _ui_info_selection_text->moveCursor(QTextCursor::Start); /* Insert the new text on the begin */ +void Interface_graphic::selection_information_clear() const { + _ui_info_selection_tabs->clear(); /* Remove all tabs in the QTabWidget*/ +} +void Interface_graphic::selection_information_show() const { _ui_info_window->show(); /* show info_window */ } +void Interface_graphic::selection_information_new_tab(const string &s) const { + QWidget *tab = new QWidget(_ui_info_selection_tabs); + _ui_info_selection_tabs->addTab(tab, QString::fromStdString(s)); +} + +void Interface_graphic::selection_information(const string &s) const { + const int tab_number = _ui_info_selection_tabs->count(); + if (tab_number) { + + QString buf = QString::fromStdString(s); + + QVBoxLayout *layout = new QVBoxLayout(_ui_info_selection_tabs->widget(tab_number - 1)); /*Make the text box resize when window is resized*/ + + QTextEdit *text_widget = new QTextEdit(); + + text_widget->setReadOnly(true); + text_widget->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); + + text_widget->insertHtml(QStringLiteral("<font color='blue'>") + buf + QStringLiteral("</font>")); + text_widget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + text_widget->moveCursor(QTextCursor::Start); /* Insert the new text on the begin */ + + layout->addWidget(text_widget); + layout->setEnabled(true); + layout->setContentsMargins(0, 0, 0, 0); + } +} + /*********************************** * * Tool functions. @@ -675,7 +703,7 @@ void Interface_graphic::on_close_triggered() { * Clear the informative window texts and hide it. */ _ui_info_trace_text->clear(); /* Clear the current text (if exists) */ - _ui_info_selection_text->clear(); /* Clear the current text (if exists) */ + _ui_info_selection_tabs->clear(); /* Clear the current text (if exists) */ _ui_info_window->hide(); /* Hide the informative window */ if (_ui_settings) { diff --git a/src/interface/Interface_graphic.hpp b/src/interface/Interface_graphic.hpp index 22270edd..fdb187c2 100644 --- a/src/interface/Interface_graphic.hpp +++ b/src/interface/Interface_graphic.hpp @@ -235,7 +235,7 @@ protected: /*! * \brief Text area which informs the user about the selected entity information. */ - QTextEdit *_ui_info_selection_text; + QTabWidget *_ui_info_selection_tabs; /*! * \brief The menu where recent files are printed @@ -364,6 +364,18 @@ public: * **********************************/ + /*! + * \brief Clear the entity tabs in the info window. + */ + void selection_information_clear() const override; + + /*! + * \brief Show the info window. + */ + void selection_information_show() const override; + + virtual void selection_information_new_tab(const std::string &) const override; + /*! * \brief The function takes strings and/or numbers then displayed it in the entity informative text area in the info window. * \param string The string to be displayed. -- GitLab