Skip to content

Commit

Permalink
added following specific process
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas.with@st.ovgu.de committed Feb 27, 2023
1 parent 71ee2d8 commit 25bbee5
Show file tree
Hide file tree
Showing 8 changed files with 356 additions and 20 deletions.
1 change: 1 addition & 0 deletions pgdb.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<file>res/breakpoint.svg</file>
<file compressed="true">ui/about_dialog.glade</file>
<file compressed="true">ui/breakpoint_dialog.glade</file>
<file compressed="true">ui/follow_dialog.glade</file>
<file compressed="true">ui/startup_dialog.glade</file>
<file compressed="true">ui/window.glade</file>
</gresource>
Expand Down
2 changes: 1 addition & 1 deletion src/master/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ $(BUILDDIR)/libmigdb.a:
$(BUILDDIR)/resources.c:
cd $(ROOTDIR) && glib-compile-resources pgdb.gresource.xml --target=bin/resources.c --generate-source

$(BUILDDIR)/pgdb: $(addprefix $(BUILDDIR)/, $(addsuffix .o, startup breakpoint breakpoint_dialog canvas window master resources)) $(BUILDDIR)/libmigdb.a
$(BUILDDIR)/pgdb: $(addprefix $(BUILDDIR)/, $(addsuffix .o, startup breakpoint breakpoint_dialog follow_dialog canvas window master resources)) $(BUILDDIR)/libmigdb.a
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(GTKMM) $(GTKSRCVIEW) $(LIBSSH)

$(BUILDDIR)/%.o: %.cpp
Expand Down
122 changes: 122 additions & 0 deletions src/master/follow_dialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
This file is part of ParallelGDB.
Copyright (c) 2023 by Nicolas With
ParallelGDB 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 3 of the License, or
(at your option) any later version.
ParallelGDB 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 ParallelGDB. If not, see <https://www.gnu.org/licenses/>.
*/

/**
* @file follow_dialog.cpp
*
* @brief Contains the implementation of the FollowDialog class.
*
* This file contains the implementation of the FollowDialog class.
*/

#include <string>

#include "follow_dialog.hpp"

using std::string;

/**
* This function is a wrapper for the Gtk::get_widget function.
*
* @tparam T The widget class.
*
* @param[in] widget_name The widget name.
*
* @return The pointer to the widget object on success, @c nullptr on error.
*/
template <class T>
T *FollowDialog::get_widget(const std::string &widget_name)
{
T *widget;
m_builder->get_widget<T>(widget_name, widget);
return widget;
}

/**
* This is the default constructor for the FollowDialog class. It will generate
* a grid of radiobuttons for the user to select the process to follow.
*
* @param num_processes The number of processes.
*
* @param max_buttons_per_row The number of buttons per grid row.
*/
FollowDialog::FollowDialog(const int num_processes, const int max_buttons_per_row)
: m_num_processes(num_processes),
m_max_buttons_per_row(max_buttons_per_row)
{
// parse glade file
m_builder =
Gtk::Builder::create_from_resource("/pgdb/ui/follow_dialog.glade");
m_dialog = get_widget<Gtk::Dialog>("dialog");

// generate radiobuttons grid
m_grid = get_widget<Gtk::Grid>("radiobuttons-grid");
Gtk::RadioButton *first_radiobutton = Gtk::manage(new Gtk::RadioButton("0"));
m_grid->attach(*first_radiobutton, 0, 0);
Gtk::RadioButton::Group radiobutton_group = first_radiobutton->get_group();
for (int rank = 1; rank < m_num_processes; ++rank)
{
Gtk::RadioButton *radiobutton =
Gtk::manage(new Gtk::RadioButton(std::to_string(rank)));
radiobutton->set_group(radiobutton_group);
m_grid->attach(*radiobutton, rank % m_max_buttons_per_row,
rank / m_max_buttons_per_row);
}

// connect signal handlers
m_dialog->signal_response().connect(
sigc::mem_fun(*this, &FollowDialog::on_dialog_response));

m_dialog->add_button("Ok", Gtk::RESPONSE_OK);
m_dialog->show_all();
}

/**
* Closes the dialog and destroys the object.
*/
FollowDialog::~FollowDialog()
{
delete m_dialog;
}

/**
* This function gets called when the user clicks on the "Ok" button or the
* close button. Checks which radiobutton is selected and saves the rank for
* later use.
*
* @param response_id The response ID of the pressed button.
*/
void FollowDialog::on_dialog_response(const int response_id)
{
if (Gtk::RESPONSE_OK != response_id)
{
return;
}
for (int rank = 0; rank < m_num_processes; ++rank)
{
Gtk::RadioButton *radiobutton =
dynamic_cast<Gtk::RadioButton *>(m_grid->get_child_at(
rank % m_max_buttons_per_row, rank / m_max_buttons_per_row));
if (radiobutton->get_active())
{
m_follow_rank = rank;
break;
}
}
}
84 changes: 84 additions & 0 deletions src/master/follow_dialog.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
This file is part of ParallelGDB.
Copyright (c) 2023 by Nicolas With
ParallelGDB 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 3 of the License, or
(at your option) any later version.
ParallelGDB 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 ParallelGDB. If not, see <https://www.gnu.org/licenses/>.
*/

/**
* @file follow_dialog.hpp
*
* @brief Header file for the FollowDialog class.
*
* This is the header file for the FollowDialog class.
*/

#ifndef FOLLOW_DIALOG_HPP
#define FOLLOW_DIALOG_HPP

#include <gtkmm.h>
#include <iosfwd>

/// A wrapper class for a Gtk::Dialog.
/**
* This is a wrapper class for a Gtk::Dialog. It will generate a dialog for the
* user to select the processes to follow.
*/
class FollowDialog
{
const int m_num_processes;
const int m_max_buttons_per_row;

int m_follow_rank;

Glib::RefPtr<Gtk::Builder> m_builder;
Gtk::Dialog *m_dialog;
Gtk::Grid *m_grid;

/// Signal handler for the accept/close action of the dialog.
void on_dialog_response(const int response_id);

/// Wrapper for the Gtk::get_widget function.
template <class T>
T *get_widget(const std::string &widget_name);

public:
/// Default constructor.
FollowDialog(const int num_processes, const int max_buttons_per_row);
/// Destructor.
~FollowDialog();

/// Runs the dialog.
/**
* This function runs the dialog.
*
* @return The response ID.
*/
inline int run()
{
return m_dialog->run();
}

/// Returns the process rank to follow.
/**
* @return The processes rank to follow.
*/
inline int follow_rank() const
{
return m_follow_rank;
}
};

#endif /* FOLLOW_DIALOG_HPP */
45 changes: 38 additions & 7 deletions src/master/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "window.hpp"
#include "breakpoint.hpp"
#include "breakpoint_dialog.hpp"
#include "follow_dialog.hpp"
#include "canvas.hpp"

using asio::ip::tcp;
Expand All @@ -58,6 +59,7 @@ const char *const open_file_id = "open-file";
*/
UIWindow::UIWindow(const int num_processes)
: m_num_processes(num_processes),
m_follow_rank(0),
m_sent_run(false)
{
// allocate memory
Expand Down Expand Up @@ -307,6 +309,10 @@ bool UIWindow::init(Glib::RefPtr<Gtk::Application> app)
sigc::mem_fun(*this, &UIWindow::on_key_press), false);
m_root_window->signal_delete_event().connect(
sigc::mem_fun(*this, &UIWindow::on_delete));
get_widget<Gtk::Button>("follow-process-button")
->signal_clicked()
.connect(
sigc::mem_fun(*this, &UIWindow::on_follow_button_clicked));
get_widget<Gtk::Button>("step-over-button")
->signal_clicked()
.connect(sigc::bind(
Expand Down Expand Up @@ -422,6 +428,22 @@ bool UIWindow::on_delete(GdkEventAny *)
return false;
}

/**
* This function opens a dialog to select the process to follow.
*/
void UIWindow::on_follow_button_clicked()
{
std::unique_ptr<FollowDialog> dialog = std::make_unique<FollowDialog>(
m_num_processes, m_max_buttons_per_row);
if (Gtk::RESPONSE_OK != dialog->run())
{
return;
}
m_follow_rank = dialog->follow_rank();
get_widget<Gtk::Button>("follow-process-button")
->set_label("Following Process " + std::to_string(m_follow_rank));
}

/**
* This function scrolls a scrolled window to the bottom. After scrolling the
* event listener is deleted, so that the user can freely scroll in the ouput.
Expand Down Expand Up @@ -1097,12 +1119,15 @@ void UIWindow::append_overview_row(const string &basename,
*
* @param[in] fullpath The fullpath of the source file to append.
*/
void UIWindow::append_source_file(const string &fullpath)
void UIWindow::append_source_file(const string &fullpath, const int rank)
{
// check that file is not opened already
if (m_opened_files.find(fullpath) != m_opened_files.end())
{
m_files_notebook->set_current_page(m_path_2_pagenum[fullpath]);
if (rank == m_follow_rank)
{
m_files_notebook->set_current_page(m_path_2_pagenum[fullpath]);
}
return;
}
m_opened_files.insert(fullpath);
Expand Down Expand Up @@ -1156,7 +1181,10 @@ void UIWindow::append_source_file(const string &fullpath)
}
scrolled_window->show_all();
int page_num = m_files_notebook->append_page(*scrolled_window, *label);
m_files_notebook->set_current_page(page_num);
if (rank == m_follow_rank)
{
m_files_notebook->set_current_page(page_num);
}
m_path_2_pagenum[fullpath] = page_num;
m_pagenum_2_path[page_num] = fullpath;
m_path_2_view[fullpath] = source_view;
Expand Down Expand Up @@ -1228,7 +1256,7 @@ void UIWindow::open_file()
if (Gtk::RESPONSE_OK == dialog->run())
{
string fullpath = dialog->get_filename();
append_source_file(fullpath);
append_source_file(fullpath, m_follow_rank);
}
dialog.reset();
}
Expand Down Expand Up @@ -1402,8 +1430,11 @@ void UIWindow::do_scroll(const int rank) const
*/
void UIWindow::scroll_to_line(const int rank) const
{
Glib::signal_idle().connect_once(
sigc::bind(sigc::mem_fun(this, &UIWindow::do_scroll), rank));
if (rank == m_follow_rank)
{
Glib::signal_idle().connect_once(
sigc::bind(sigc::mem_fun(this, &UIWindow::do_scroll), rank));
}
}

/**
Expand Down Expand Up @@ -1523,7 +1554,7 @@ void UIWindow::print_data_gdb(const char *const data, const int rank)
// this index is one-based!
const int line = stop_record->frame->line;
set_position(rank, fullpath, line);
append_source_file(fullpath);
append_source_file(fullpath, rank);
scroll_to_line(rank);
}
mi_free_stop(stop_record);
Expand Down
5 changes: 4 additions & 1 deletion src/master/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class UIWindow
{
const int m_num_processes;
int m_max_buttons_per_row;
int m_follow_rank;

int *m_current_line;
std::string *m_current_file;
Expand Down Expand Up @@ -127,7 +128,7 @@ class UIWindow
void append_overview_row(const std::string &basename,
const std::string &fullpath);
/// Appends a source file page to the source view notebook.
void append_source_file(const std::string &fullpath);
void append_source_file(const std::string &fullpath, const int rank);
/// Tokenizes, parses and analyzes the received GDB output.
void print_data_gdb(const char *const data, const int rank);
/// Appends text to the target I/O text view.
Expand Down Expand Up @@ -182,6 +183,8 @@ class UIWindow
void on_about_clicked();
/// Terminates the slaves and then quits the application.
void on_quit_clicked();
/// Opens a dialog to select the process to follow.
void on_follow_button_clicked();
/// Signal handler for all the interaction buttons.
void on_interaction_button_clicked(const int key_value);
/// Signal handler for key-press events.
Expand Down
Loading

0 comments on commit 25bbee5

Please sign in to comment.