diff --git a/src/core/Core.cpp b/src/core/Core.cpp index c186c5f372881eb5a35a0c4701cc138f0ede8047..5227019b1995b0fdc39c199bff21f1e4b7f570dd 100644 --- a/src/core/Core.cpp +++ b/src/core/Core.cpp @@ -370,7 +370,8 @@ Trace *Core::build_trace(const std::string &filename, bool is_state_splitting) { return nullptr; } - Trace *trace = new Trace(filename); + QFileInfo filepath(QString::fromStdString(filename)); + Trace *trace = new Trace(filepath.absoluteFilePath().toStdString()); #if defined(USE_ITC) && defined(BOOST_SERIALIZE) if (Info::Splitter::path.empty()) diff --git a/src/interface/Interface_graphic.cpp b/src/interface/Interface_graphic.cpp index 7f620f6ca4b4f5db2085fd083539a312f2fc1c94..cc64ff9baeae4f682112cfa6b9c0903340fdebdc 100644 --- a/src/interface/Interface_graphic.cpp +++ b/src/interface/Interface_graphic.cpp @@ -111,7 +111,7 @@ Interface_graphic::Interface_graphic(Core *core, QWidget *parent) : _plugin_window = nullptr; _ui_settings = nullptr; _ui_node_selection = nullptr; - _ui_interval_selection = nullptr; + _ui_interval_selection = new IntervalSelect(this); // For drag and drop operations setAcceptDrops(true); @@ -275,7 +275,6 @@ void Interface_graphic::on_reload_triggered() { } // if(_ui_node_selection!=NULL) // _ui_node_selection->on_reset_button_clicked(); - // if(_ui_interval_selection!=NULL) // _ui_interval_selection->on_reset_button_clicked(); if (_reload_type) { release_render_area(); @@ -295,9 +294,7 @@ void Interface_graphic::on_reload_triggered() { _render_layouts.front()->get_scale_container_slider()->setValue(20); // update the interval selection display - if (_ui_interval_selection != nullptr) { - _ui_interval_selection->update_interval_layout_from_render_view(_render_layouts.front()); - } + _ui_interval_selection->update_interval_layout_from_render_view(_render_layouts.front()); } } @@ -334,10 +331,6 @@ void Interface_graphic::remove_render_area(RenderLayout *render_layout) { //_plugin_window->clear_plugins(); } - if (nullptr != _ui_interval_selection) { - _ui_interval_selection->hide(); - } - // Remove RenderLayout from _render_layouts which is a vector for (std::vector<RenderLayout *>::iterator it = _render_layouts.begin(); it != _render_layouts.end(); ++it) { if (*it == render_layout) { @@ -346,6 +339,12 @@ void Interface_graphic::remove_render_area(RenderLayout *render_layout) { } } + update_trace_names(); + + if (_ui_interval_selection->isVisible()) { + _ui_interval_selection->update_container(_render_layouts); + } + if (_render_layouts.empty()) { background_widget->show(); } @@ -357,8 +356,6 @@ void Interface_graphic::on_quit_triggered() { if (nullptr != _ui_node_selection) ((QWidget *)_ui_node_selection)->close(); - if (nullptr != _ui_interval_selection) - ((QWidget *)_ui_interval_selection)->close(); if (nullptr != _ui_info_window) ((QWidget *)_ui_info_window)->close(); ((QWidget *)this)->close(); @@ -492,19 +489,7 @@ void Interface_graphic::on_node_selection_triggered() { } void Interface_graphic::on_interval_selection_triggered() { - - if (_render_layouts.empty()) { - error("Must load a trace before using interval selection on a trace"); - return; - } - if (!_ui_interval_selection) { - _ui_interval_selection = new IntervalSelect(this); - connect(quit, &QAction::triggered, _ui_interval_selection, &QWidget::close); - } _ui_interval_selection->update_container(_render_layouts); - for (const RenderLayout *render_layout: _render_layouts) { - _ui_interval_selection->update_interval_layout_from_render_view(render_layout); - } _ui_interval_selection->show(); } @@ -544,9 +529,6 @@ void Interface_graphic::closeEvent(QCloseEvent *event) { if (_ui_node_selection) _ui_node_selection->close(); - - if (_ui_interval_selection) - _ui_interval_selection->close(); } Core *Interface_graphic::get_console() { @@ -683,8 +665,13 @@ bool Interface_graphic::open_trace(const QString &filepath) { // This is because the Render in draw_trace access the trace max_time // by getting it from the RenderLayout set_trace(trace); + update_trace_names(); draw_trace(trace, _render_layouts.size() - 1); + if (_ui_interval_selection->isVisible()) { + _ui_interval_selection->update_container(_render_layouts); + } + return true; } @@ -923,7 +910,7 @@ void Interface_graphic::set_trace(Trace *trace) { } void Interface_graphic::update_interval_select_window(const RenderLayout *render_layout) { - if (nullptr != _ui_interval_selection) { + if (_ui_interval_selection->isVisible()) { _ui_interval_selection->update_interval_layout_from_render_view(render_layout); } } @@ -944,4 +931,72 @@ void Interface_graphic::draw_trace(Trace *trace, const int &index) { QApplication::restoreOverrideCursor(); } +void Interface_graphic::update_trace_names() { + // If there is no RenderLayout do nothing + if (_render_layouts.empty()) { + return; + } + + // Build the filepath list + std::vector<const std::string *> filepath_list; + for (RenderLayout *render_layout: _render_layouts) { + filepath_list.push_back(&render_layout->get_trace()->get_filepath()); + } + + // Compute the length of the common part between every filepath + const int common_part_length = filepath_common_part_length(filepath_list); + + for (RenderLayout *render_layout: _render_layouts) { + // Set the filename to be the filepath from which the common part has been removed + render_layout->get_trace()->set_filename(render_layout->get_trace()->get_filepath().substr(common_part_length)); + } +} + +int Interface_graphic::filepath_common_part_length(const std::vector<const std::string *> &filepath_list) { + // It no file path, the common part is null + if (filepath_list.empty()) { + return 0; + } + + const char separator = QDir::separator().toLatin1(); + std::string common_string = *filepath_list.front(); + + // If there is only one file path, + // Find the length of its dir path by checking the position of the last dir separator + // Add one to account for the separator itself + if (filepath_list.size() == 1) { + return common_string.find_last_of(separator) + 1; + } + + // Otherwise we need to compare each file path + int common_string_length = 0; + + for (int index = 1; index < filepath_list.size(); ++index) { + const std::string *filepath = filepath_list.at(index); + + // Check if filepath is not nullptr + if (!filepath) { + continue; + } + + // Iterate over every chars in the common part + for (int char_index = 0; char_index < common_string.length(); ++char_index) { + // If the char is different from the one in the filepath + if (common_string.at(char_index) != filepath->at(char_index)) { + // Truncate the end of the common part + common_string = common_string.substr(0, common_string_length); + break; + } + + // If the common char is a separator, the index is saved + if (common_string.at(char_index) == separator) { + common_string_length = char_index; + } + } + } + + // Add 1 to account for the last separator itself + return common_string_length + 1; +} + #include "moc_Interface_graphic.cpp" diff --git a/src/interface/Interface_graphic.hpp b/src/interface/Interface_graphic.hpp index 82549410ad191e1b7e3339ef186b1552312ac4aa..5642d8d2e50fc43c824704baafbf1d2d35e278a4 100644 --- a/src/interface/Interface_graphic.hpp +++ b/src/interface/Interface_graphic.hpp @@ -197,6 +197,24 @@ protected: */ QAction *_recent_file_actions[Session::_MAX_NB_RECENT_FILES]; + /*! + * \brief Update prefix of trace names when loading or closing a trace. + * + * Each trace contains the absolute path to its file, but this is too long to display. + * Thus, the trace contains a shorter name (_filename), + * long enough to be distinct from other loaded traces. + */ + void update_trace_names(); + + /*! + * \brief Return the length of the path of the common directory between a list of file path + * \param string_list A list of file path + * + * Examples : For "/home/foo.paje" and "/home/foo_bis.paje" the common dir path is "/home/" of length 6 + * For "/home/foo.paje" and "/toto/foo.paje" the common dir path is "/" of length 1 + */ + int filepath_common_part_length(const std::vector<const std::string *> &filepath_list); + public: /*********************************** * diff --git a/src/interface/IntervalSelect.cpp b/src/interface/IntervalSelect.cpp index f7413c9a16c94bd8c7a3788eecffa0cda7712309..0cfd779275f0809879c37a990c7b0c59fb4eb523 100644 --- a/src/interface/IntervalSelect.cpp +++ b/src/interface/IntervalSelect.cpp @@ -38,9 +38,23 @@ void IntervalSelect::update_container(const std::vector<RenderLayout *> &render_ // Fill interval select layouts with up to date layouts for (RenderLayout *render_layout: render_layouts) { _interval_select_layouts.push_back(new IntervalSelectLayout(this, render_layout)); + update_interval_layout_from_render_view(render_layout); interval_select_container_layout->addWidget(_interval_select_layouts.back()); } + if (_interval_select_layouts.empty()) { + setFixedHeight(190); + interval_select_container_widget->setFixedHeight(170); + error_panel->show(); + auto_refresh_box->hide(); + reset_all_button->hide(); + apply_button->hide(); + close_button->hide(); + return; + } + + error_panel->hide(); + // Set window size and button position depending on the number of layouts to display int container_height = _interval_select_layouts.size() * 170; @@ -50,6 +64,10 @@ void IntervalSelect::update_container(const std::vector<RenderLayout *> &render_ reset_all_button->setGeometry(260, container_height + 100, 75, 25); apply_button->setGeometry(350, container_height + 100, 75, 25); close_button->setGeometry(440, container_height + 100, 75, 25); + auto_refresh_box->show(); + reset_all_button->show(); + apply_button->show(); + close_button->show(); } void IntervalSelect::update_interval_layout_from_render_view(const RenderLayout *render_layout) { diff --git a/src/interface/IntervalSelectLayout.cpp b/src/interface/IntervalSelectLayout.cpp index 8a8e3b2f0ad5787e56be94d53a4af3ffc85ec612..d16be9301e35f6dc92237b567878017fc17f5039 100644 --- a/src/interface/IntervalSelectLayout.cpp +++ b/src/interface/IntervalSelectLayout.cpp @@ -27,7 +27,8 @@ IntervalSelectLayout::IntervalSelectLayout(IntervalSelect *interval_select, RenderLayout *render_layout) : QGroupBox(interval_select), _interval_select(interval_select), _render_layout(std::move(render_layout)) { - setTitle(QString::fromStdString(_render_layout->get_trace()->get_filename()).split(QString::fromStdString("/")).last() + QString::fromStdString(" ")); + // Spaces are added at the end otherwise the text can be clipped depending on the default font (under Debian for example) + setTitle(QString::fromStdString(_render_layout->get_trace()->get_filename()) + QString::fromStdString(" ")); setFixedHeight(150); // Initialize spin box labels diff --git a/src/interface/SelectInfo.cpp b/src/interface/SelectInfo.cpp index f3cb1078e31716761721b7df5cc433d4cfe92acc..c06a06afa46ed3d64855b0d8152ac98f812f81e7 100644 --- a/src/interface/SelectInfo.cpp +++ b/src/interface/SelectInfo.cpp @@ -57,11 +57,6 @@ void SelectInfo::add_info_tab(const std::string &tab_name, const std::string &co _entity_dates.insert(std::move(entity_dates_pair)); } -void SelectInfo::set_title(const QString &title) { - // Spaces are added at the end otherwise the text can be clipped depending on the default font (under Debian for example) - this->setWindowTitle(title + QString::fromStdString(" ")); -} - void SelectInfo::on_info_selection_tab_currentChanged() { // If there is no tab, hide the buttons if (info_selection_tab->count() == 0) { @@ -89,6 +84,7 @@ void SelectInfo::on_info_selection_tab_currentChanged() { } void SelectInfo::show_window() { + this->setWindowTitle(QString::fromStdString(_render_layout->get_trace()->get_filename())); on_info_selection_tab_currentChanged(); show(); } diff --git a/src/interface/SelectInfo.hpp b/src/interface/SelectInfo.hpp index eb2657005dfcbebb495d2bfc9a49dbf27834308f..228c2573e76b315127eeb3cb10751709b7ce39bf 100644 --- a/src/interface/SelectInfo.hpp +++ b/src/interface/SelectInfo.hpp @@ -78,12 +78,6 @@ public: */ void show_window(); - /*! - * \brief Set the title of the SelectInfo window - * \param title the new title - */ - void set_title(const QString &title); - private Q_SLOTS: /*! * \brief Update the way buttons are displayed depending on the type of Entity current tab shows diff --git a/src/interface/ui/interval_select.ui b/src/interface/ui/interval_select.ui index 2eedd46caa348cd6cd61c9657bf2670279b8f5af..11f51aeca2d0ef5670b261c00a32c991fc17a2a5 100644 --- a/src/interface/ui/interval_select.ui +++ b/src/interface/ui/interval_select.ui @@ -89,7 +89,28 @@ <height>200</height> </rect> </property> - <layout class="QVBoxLayout" name="interval_select_container_layout"/> + <layout class="QVBoxLayout" name="interval_select_container_layout"> + <item> + <widget class="QTextEdit" name="error_panel"> + <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" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +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 align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p align="center" 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-size:14pt; color:#e01b24;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#e01b24;">There is no displayed trace.</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#e01b24;">Please open a trace to access this tool.</span></p></body></html></string> + </property> + </widget> + </item> + </layout> </widget> </widget> <resources/> diff --git a/src/render/RenderLayout.cpp b/src/render/RenderLayout.cpp index 8c9aa59967d1aef8e3412a4faaee70a40e1161cd..ad199953a071713f27394007a769a764f741d655 100644 --- a/src/render/RenderLayout.cpp +++ b/src/render/RenderLayout.cpp @@ -290,7 +290,6 @@ SelectInfo *RenderLayout::get_select_info_window() { void RenderLayout::set_trace(Trace *trace) { _trace = trace; - _select_info_window.set_title(QString::fromStdString(trace->get_filename())); } Trace *RenderLayout::get_trace() const { diff --git a/src/trace/Trace.cpp b/src/trace/Trace.cpp index 0e2588bd13e22c982415fa5e4fe2678c43f43cf8..8c4414de60af351fc99cc7e9386c736da007d189 100644 --- a/src/trace/Trace.cpp +++ b/src/trace/Trace.cpp @@ -77,8 +77,10 @@ bool Trace::_sub_trace_to_load = false; Date Trace::_begin_trace; Date Trace::_end_trace; -Trace::Trace(const std::string &filename) : - _max_date(0.0), _filename(filename) { +Trace::Trace(const std::string &filepath) : + _max_date(0.0), + _filename(""), + _filepath(filepath) { _selected_container = nullptr; _filter = 0; _interval_constrained = nullptr; @@ -935,10 +937,18 @@ Trace::get_all_entityvalues(const string &type) { return nullptr; } +const std::string &Trace::get_filepath() const { + return _filepath; +} + const std::string &Trace::get_filename() const { return _filename; } +void Trace::set_filename(const std::string &filename) { + _filename = filename; +} + bool Trace::load_config_from_xml(const QString &filename) { QDomDocument doc(QStringLiteral("Subset")); QFile file(filename); diff --git a/src/trace/Trace.hpp b/src/trace/Trace.hpp index 9968bd5717d6ae9b0af3e52bd50b505218a3b4b1..879e0465cb4aacde84fe6022fd3933f467ff56ae 100644 --- a/src/trace/Trace.hpp +++ b/src/trace/Trace.hpp @@ -66,8 +66,16 @@ class Trace private: Date _max_date; + /*! + * \brief Short name for the trace, used for display + */ std::string _filename; + /*! + * \brief Absolute file path of the trace + */ + std::string _filepath; + std::list<ContainerType *> _root_container_types; Container::Vector _root_containers; Container::Vector _view_root_containers; @@ -119,7 +127,7 @@ private: } public: - Trace(const std::string &filename); + Trace(const std::string &filepath); ~Trace(); static void select_sub_trace(const Date &begin, const Date &end) { @@ -393,8 +401,11 @@ public: */ const std::map<std::string, LinkType *> *get_link_types() const; + const std::string &get_filepath() const; const std::string &get_filename() const; + void set_filename(const std::string &filename); + /*! * \fn search_container_type(const String &name) const * \brief Search a container type by his name or alias