bellow is the code according to execution flow and some gdb output, the most relevant functions are start_timer, stop_timer and timeout_timer from Time_Keeper and UI_Controller
u-i-controller.h
#ifndef _U_I_CONTROLLER_H_
#define _U_I_CONTROLLER_H_
#include <unistd.h>
#include <gtkmm.h>
#include <unordered_map>
#include <glibmm/datetime.h>
#include <time-keeper.h>
namespace std{
template <>
struct hash<Time_Keeper>
{
size_t operator()( Time_Keeper& t) const
{
return t.hasheable().hash();
}
};
}
class UI_Controller
{
public:
UI_Controller(Gtk::Builder* refference,Gtk::Application * app);
void deffine_application(Gtk::Application * app);
void add_window_to_application(Gtk::Window * window);
protected:
private:
Gtk::Builder * refference;
Gtk::ApplicationWindow * content_relations;
Gtk::Application * app;
std::vector<Glib::RefPtr<Glib::Object>> widgets;
std::unordered_map<int,Time_Keeper> bind_time;
void show_window(Gtk::Window *window);
void start_timer(Gtk::Widget * selected, int position);
void stop_timer(int i) { (bind_time[i]).stop_timer (); };
void restart_timer(int i) { return ;}; // to be done
void add_timer(int i) { return ;}; //to be done
bool timeout_timer(Gtk::Label * display,int position);
};
#endif // _U_I_CONTROLLER_H_
u-i-controller.cc
#include "u-i-controller.h"
UI_Controller::UI_Controller(Gtk::Builder * refference, Gtk::Application * app)
{
deffine_application (app);
this->refference = refference;
refference->get_widget("main_window",this->content_relations);
widgets = refference->get_objects();
Glib::ustring widget_names = "";
for (int i=0; i < widgets.size(); i++){
widget_names = widget_names+dynamic_cast<Gtk::Widget*>(widgets.at(i).get())->get_name()+"\n";
if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "start_timer"){
//dynamic_cast<Gtk::Widget*>(widgets.at(i).get())->get_ancestor(GTK_TYPE_BOX)
//dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::mem_fun(*this,&Controlador_UI::botao_acionado));
dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind<Gtk::Widget*>(sigc::mem_fun(*this,&UI_Controller::start_timer),dynamic_cast<Gtk::Widget*>(widgets.at(i).get()),i ) );
}
if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "stop_timer"){
dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::stop_timer),i ) );
}
if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "restart_timer"){
dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::restart_timer),i ) );
}
if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "add_timer"){
dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::add_timer),i ) );
}
}
app->run();
}
void UI_Controller::deffine_application(Gtk::Application * app)
{
this->app = app;
}
void UI_Controller::add_window_to_application (Gtk::Window * window)
{
app->add_window(*window);
}
void UI_Controller::show_window(Gtk::Window * window)
{
add_window_to_application(window);
window->show();
window->show_all_children();
}
void UI_Controller::start_timer(Gtk::Widget * selected, int position){
if (bind_time.find(position) == bind_time.end() ){
bind_time [position] = *(new Time_Keeper());
(bind_time [position]).start_timer ();
}
Gtk::Label * display;
refference->get_widget("timer_display",display);
// both 2 variables bellow yet to be managed by this class
sigc::slot<bool()> my_slot = sigc::bind(sigc::mem_fun(*this,
&UI_Controller::timeout_timer), display, position);
auto conn = Glib::signal_timeout().connect(my_slot, 100);
}
bool UI_Controller::timeout_timer(Gtk::Label * display,int position){
if ( ((bind_time [position]).get_active()) ) display->set_text((bind_time [position]).display_timer ());
return (bind_time [position]).get_active();
}
reduced Time_Keeper class
#ifndef _TIME_KEEPER_H_
#define _TIME_KEEPER_H_
#include <glibmm/datetime.h>
#include<memory>
#include <glibmm/timer.h>
class Time_Keeper
{
public:
void start_timer();
void stop_timer();
// I would rather use the constructor, but I need a default one in order \
to use the unordered list
Glib::DateTime hasheable() { return Glib::DateTime::create_now_local(); }
bool get_active() { return active; };
protected:
private:
std::shared_ptr<Glib::Timer> timer;
bool active = false;
};
#endif // _TIME_KEEPER_H_
#include "time-keeper.h"
void Time_Keeper::start_timer(){
active = true;
timer = std::shared_ptr<Glib::Timer>(new Glib::Timer);
timer.get()->start();
};
void Time_Keeper::stop_timer(){
active = false;
timer.get()->stop();
}
main
#include <gtkmm.h>
#include <iostream>
#include "config.h"
#ifdef ENABLE_NLS
# include <libintl.h>
#endif
#include "u-i-controller.h"
/* For testing propose use the local (not installed) ui file */
/* #define UI_FILE PACKAGE_DATA_DIR"/ui/time_keeper.ui" */
#define UI_FILE "src/time_keeper.ui"
Gtk::ApplicationWindow * main_win = 0;
void activate_app(Gtk::Application * app)
{
app->add_window(*main_win);
main_win->show();
main_win->show_all_children ();
}
int
main (int argc, char *argv[])
{
auto app = Gtk::Application::create(argc,argv,"org.gtkmm.time_keeper");
//Load the Glade file and instiate its widgets:
Glib::RefPtr<Gtk::Builder> builder;
try
{
builder = Gtk::Builder::create_from_file(UI_FILE);
}
catch (const Glib::FileError & ex)
{
std::cerr << ex.what() << std::endl;
return 1;
}
builder->get_widget("main_window", main_win);
if (main_win)
{
app->signal_startup().connect(sigc::bind<Gtk::Application*>(sigc::ptr_fun(&activate_app), app.get() ) );
UI_Controller * controller = new UI_Controller(builder.get(),app.get());
}
}
time_keeper.ui
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkApplicationWindow" id="main_window">
<property name="can-focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">13</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">current activity time</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<!-- n-columns=4 n-rows=3 -->
<object class="GtkGrid" id="timer_grid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="start_timer">
<property name="label" translatable="yes">Start</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="stop_timer">
<property name="label" translatable="yes">Stop</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="restart_timer">
<property name="label" translatable="yes">Restart</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="add_timer">
<property name="label" translatable="yes">+</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">0</property>
<property name="height">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="timer_display">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="width">3</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">activity limit</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<!-- n-columns=4 n-rows=3 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Start</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Stop</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Restart</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">+</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">0</property>
<property name="height">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="width">3</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
execution stack from gdb, yellow line indicates the last executed code