diff --git a/src/add_request_dialog.cc b/src/add_request_dialog.cc index ecfa5cf..b3c8077 100644 --- a/src/add_request_dialog.cc +++ b/src/add_request_dialog.cc @@ -38,6 +38,7 @@ using namespace sgpem; using namespace Gtk; using namespace Glib; using Gnome::Glade::Xml; +using std::vector; AddRequestDialog::AddRequestDialog(BaseObjectType* cobject, const RefPtr& glade) : Dialog(cobject), _glade(glade) @@ -47,6 +48,9 @@ AddRequestDialog::AddRequestDialog(BaseObjectType* cobject, const RefPtr& g _glade->get_widget("Remove", _remove_button); _glade->get_widget("Resource.Combo", _resource_combo); _glade->get_widget("OK.Button", _ok_button); + _glade->get_widget("Instant.Spin", _instant_spin); + _glade->get_widget("Duration.Spin", _duration_spin); + /** ATTACH SIGNAL HANDLERS FOR BUTTONS **/ @@ -95,31 +99,89 @@ AddRequestDialog::AddRequestDialog(BaseObjectType* cobject, const RefPtr& g sigc::mem_fun(*this, &AddRequestDialog::_on_list_selection_changed)); } -Request& -AddRequestDialog::construct_request(Thread& owner) +Request* +AddRequestDialog::run_add(Thread& owner) { - assert(_list_model->children()); + update_combo(); - SpinButton* instant_spin; - _glade->get_widget("Instant.Spin", instant_spin); - - History& h = Simulation::get_instance().get_history(); + Request* r = NULL; - Request& r = h.add_request(owner, instant_spin->get_value_as_int()); - - TreeNodeChildren sreq_container = _list_model->children(); + // reset the dialog data + _list_model->clear(); + _instant_spin->set_value(0.0); + _duration_spin->set_value(0.0); - for(Iseq it = iseq(sreq_container); it; ++it) - h.add_subrequest(r, (*it)[_list_key_column], (*it)[_list_length_column]); + if(run() == RESPONSE_OK) + { + assert(_list_model->children()); + + History& h = Simulation::get_instance().get_history(); + + r = &h.add_request(owner, _instant_spin->get_value_as_int()); + + TreeNodeChildren sreq_container = _list_model->children(); + + for(Iseq it = iseq(sreq_container); it; ++it) + h.add_subrequest(*r, (*it)[_list_key_column], (*it)[_list_length_column]); + } + + hide(); return r; } void -AddRequestDialog::on_show() +AddRequestDialog::run_edit(Request& request) { - //TODO is this a reasonable place where to fill the combo model? + update_combo(); + + _list_model->clear(); + + History& history = Simulation::get_instance().get_history(); + const Environment::Resources& resources = history.get_last_environment().get_resources(); + _instant_spin->set_value(static_cast(request.get_instant())); + + // PLEASE KEEP THIS A COPY, WE *NEED* TO COPY IT + vector subrequests = request.get_subrequests(); + + for(Iseq::iterator> it = iseq(subrequests); it; ++it) + { + SubRequest& sr = *(*it); + + TreeModel::Row row = *(_list_model->append()); + + unsigned int key = sr.get_resource_key(); + row[_list_key_column] = key; + + const ustring name = resources.find(key)->second->get_name(); + row[_list_resource_column] = name; + + row[_list_length_column] = sr.get_length(); + } + + if(run() == RESPONSE_OK) + { + assert(_list_model->children()); + + // I know it's a bit hack-ish, but do you know an elegant alternative way? + for(Iseq::iterator> it = iseq(subrequests); it; ++it) + history.remove(*(*it)); + + history.edit_request(request, _instant_spin->get_value_as_int()); + + TreeNodeChildren sreq_container = _list_model->children(); + + for(Iseq it = iseq(sreq_container); it; ++it) + history.add_subrequest(request, (*it)[_list_key_column], (*it)[_list_length_column]); + } + + hide(); +} + +void +AddRequestDialog::update_combo() +{ typedef Environment::Resources::const_iterator ResourceIt; const Environment::Resources& resources = @@ -142,10 +204,6 @@ AddRequestDialog::_on_add() { TreeModel::iterator sel = _resource_combo->get_active(); - SpinButton* duration_spin; - - _glade->get_widget("Duration.Spin", duration_spin); - TreeModel::Row row = *(_list_model->append()); const unsigned int key = (*sel)[_combo_key_column]; @@ -154,7 +212,7 @@ AddRequestDialog::_on_add() const ustring resource = (*sel)[_combo_resource_column]; row[_list_resource_column] = resource; - const unsigned int length = duration_spin->get_value_as_int(); + const unsigned int length = _duration_spin->get_value_as_int(); row[_list_length_column] = length; } diff --git a/src/add_request_dialog.hh b/src/add_request_dialog.hh index b9d6b54..b68b609 100644 --- a/src/add_request_dialog.hh +++ b/src/add_request_dialog.hh @@ -33,6 +33,7 @@ namespace sgpem #include #include #include +#include #include namespace sgpem @@ -43,17 +44,21 @@ namespace sgpem AddRequestDialog(BaseObjectType* cobject, const Glib::RefPtr& glade); /** - \brief Attemts to build a request by using the data supplied - up to now. - \note Must be called only after it has been shown at least - one time with an OK, otherwise expect undefined behaviour! + \brief Attemts to show the dialog, and constructs a request + if response is OK + \param owner The thread which will own the request */ - Request& construct_request(Thread& t); - - protected: - virtual void on_show(); - + Request* run_add(Thread& owner); + + /** + \brief Attemts to show the dialog, and modify an existing request + if response is OK + \param resource The request to modify + */ + void run_edit(Request& resource); + private: + void update_combo(); void _on_add(); void _on_remove(); void _on_list_selection_changed(); @@ -72,6 +77,8 @@ namespace sgpem Gtk::Button* _add_button; Gtk::Button* _remove_button; Gtk::Button* _ok_button; + Gtk::SpinButton* _instant_spin; + Gtk::SpinButton* _duration_spin; Gtk::ComboBox* _resource_combo; Glib::RefPtr _combo_model; diff --git a/src/schedulables_tree_widget.cc b/src/schedulables_tree_widget.cc index 1db0f12..38e6f61 100644 --- a/src/schedulables_tree_widget.cc +++ b/src/schedulables_tree_widget.cc @@ -185,6 +185,15 @@ SchedulablesTreeWidget::on_button_press_event(GdkEventButton* event) action_group->add( Gtk::Action::create("AddRequest", "Add Request"), sigc::mem_fun(*this, &SchedulablesTreeWidget::_on_add_request) ); + + action_group->add( Gtk::Action::create("EditProcess", "Edit Process"), + sigc::mem_fun(*this, &SchedulablesTreeWidget::_on_edit_process) ); + + action_group->add( Gtk::Action::create("EditThread", "Edit Thread"), + sigc::mem_fun(*this, &SchedulablesTreeWidget::_on_edit_thread) ); + + action_group->add( Gtk::Action::create("EditRequest", "Edit Request"), + sigc::mem_fun(*this, &SchedulablesTreeWidget::_on_edit_request) ); action_group->add( Gtk::Action::create("RemoveProcess", "Remove Process"), sigc::mem_fun(*this, &SchedulablesTreeWidget::_on_remove_process) ); @@ -203,43 +212,42 @@ SchedulablesTreeWidget::on_button_press_event(GdkEventButton* event) const HandleType selection_type = get_selection_type(); - Glib::ustring ui_info = - "" - " "; - - if(selection_type == htype_process) - ui_info += - " "; - else if(selection_type == htype_thread) - ui_info += - " "; - - ui_info += - " "; + Glib::ustring adds; + Glib::ustring edits; + Glib::ustring removes; + Glib::ustring separator; if(selection_type != htype_undefined) - ui_info += - " "; + separator = ""; switch(selection_type) { case htype_process: - ui_info += - " "; + adds = ""; + edits = ""; + removes = ""; break; case htype_thread: - ui_info += - " "; + adds = ""; + edits = ""; + removes = ""; break; case htype_request: - ui_info += - " "; + edits = ""; + removes = ""; break; case htype_subrequest: - ui_info += - " "; + removes = ""; } + + adds += ""; + Glib::ustring ui_info = + "" + " "; + + ui_info += adds + separator + edits + ((edits.size() == 0) ? ustring() : separator) + removes; + ui_info += " " ""; @@ -327,19 +335,63 @@ SchedulablesTreeWidget::update(const History& history) void SchedulablesTreeWidget::_on_add_process() { + add_edit_process(true); +} + +void +SchedulablesTreeWidget::_on_edit_process() +{ + add_edit_process(false); +} + +void +SchedulablesTreeWidget::add_edit_process(bool adding) +{ + /** This is ugly, I know, we should be using derived widgets, but I also believe we + * have little time, and I'm not going to waste too much of it on the frontend */ + + Entry* name_entry; + SpinButton* arrival_time_spin; + SpinButton* base_priority_spin; + + _add_process_dialog_glade->get_widget("Name.Entry", name_entry); + _add_process_dialog_glade->get_widget("ArrivalTime.Spin", arrival_time_spin); + _add_process_dialog_glade->get_widget("BasePriority.Spin", base_priority_spin); + + Process* selection = NULL; + + if(!adding) + { + selection = get_selected(); + + name_entry->set_text(selection->get_name()); + arrival_time_spin->set_value(static_cast(selection->get_arrival_time())); + base_priority_spin->set_value(static_cast(selection->get_base_priority())); + } + else + { + name_entry->set_text(""); + arrival_time_spin->set_value(0.0); + base_priority_spin->set_value(0.0); + } + + if(_add_process_dialog->run() == RESPONSE_OK) { - Entry* name_entry; - SpinButton* arrival_time_spin; - SpinButton* base_priority_spin; - _add_process_dialog_glade->get_widget("Name.Entry", name_entry); - _add_process_dialog_glade->get_widget("ArrivalTime.Spin", arrival_time_spin); - _add_process_dialog_glade->get_widget("BasePriority.Spin", base_priority_spin); - - Simulation::get_instance().get_history().add_process(name_entry->get_text(), - arrival_time_spin->get_value_as_int(), - base_priority_spin->get_value_as_int()); + if(adding) + { + Simulation::get_instance().get_history().add_process(name_entry->get_text(), + arrival_time_spin->get_value_as_int(), + base_priority_spin->get_value_as_int()); + } + else + { + Simulation::get_instance().get_history().edit_process(*selection, + name_entry->get_text(), + arrival_time_spin->get_value_as_int(), + base_priority_spin->get_value_as_int()); + } } _add_process_dialog->hide(); @@ -348,27 +400,74 @@ SchedulablesTreeWidget::_on_add_process() void SchedulablesTreeWidget::_on_add_thread() { - Process* p = get_selected(); - if(p == NULL) - return; + add_edit_thread(true); +} + +void +SchedulablesTreeWidget::_on_edit_thread() +{ + add_edit_thread(false); +} + +void +SchedulablesTreeWidget::add_edit_thread(bool adding) +{ + /** This is ugly, I know, we should be using derived widgets, but I also believe we + * have little time, and I'm not going to waste too much of it on the frontend */ + + Entry* name_entry; + SpinButton* cpu_time_spin; + SpinButton* arrival_time_spin; + SpinButton* base_priority_spin; + + _add_thread_dialog_glade->get_widget("Name.Entry", name_entry); + _add_thread_dialog_glade->get_widget("CpuTime.Spin", cpu_time_spin); + _add_thread_dialog_glade->get_widget("ArrivalTime.Spin", arrival_time_spin); + _add_thread_dialog_glade->get_widget("BasePriority.Spin", base_priority_spin); + + Thread* t = NULL; + + if(!adding) + { + t = get_selected(); + + name_entry->set_text(t->get_name()); + cpu_time_spin->set_value(static_cast(t->get_total_cpu_time())); + arrival_time_spin->set_value(static_cast(t->get_arrival_time())); + base_priority_spin->set_value(static_cast(t->get_base_priority())); + } + else + { + name_entry->set_text(""); + cpu_time_spin->set_value(1.0); + arrival_time_spin->set_value(0.0); + base_priority_spin->set_value(0.0); + } + if(_add_thread_dialog->run() == RESPONSE_OK) { - Entry* name_entry; - SpinButton* cpu_time_spin; - SpinButton* arrival_time_spin; - SpinButton* base_priority_spin; - - _add_thread_dialog_glade->get_widget("Name.Entry", name_entry); - _add_thread_dialog_glade->get_widget("CpuTime.Spin", cpu_time_spin); - _add_thread_dialog_glade->get_widget("ArrivalTime.Spin", arrival_time_spin); - _add_thread_dialog_glade->get_widget("BasePriority.Spin", base_priority_spin); - Simulation::get_instance().get_history().add_thread(name_entry->get_text(), - *p, - cpu_time_spin->get_value_as_int(), - arrival_time_spin->get_value_as_int(), - base_priority_spin->get_value_as_int()); + if(adding) + { + Process* p = get_selected(); + assert(p != NULL); + + Simulation::get_instance().get_history().add_thread(name_entry->get_text(), + *p, + cpu_time_spin->get_value_as_int(), + arrival_time_spin->get_value_as_int(), + base_priority_spin->get_value_as_int()); + } + else + { + Simulation::get_instance().get_history().edit_thread(*t, + name_entry->get_text(), + cpu_time_spin->get_value_as_int(), + arrival_time_spin->get_value_as_int(), + base_priority_spin->get_value_as_int()); + + } } @@ -380,13 +479,19 @@ SchedulablesTreeWidget::_on_add_request() { Thread* t = get_selected(); - if(t == NULL) - return; - - if(_add_request_dialog->run() == RESPONSE_OK) - _add_request_dialog->construct_request(*t); + assert(t != NULL); - _add_request_dialog->hide(); + _add_request_dialog->run_add(*t); +} + +void +SchedulablesTreeWidget::_on_edit_request() +{ + Request* r = get_selected(); + + assert(r != NULL); + + _add_request_dialog->run_edit(*r); } void diff --git a/src/schedulables_tree_widget.hh b/src/schedulables_tree_widget.hh index 2df1d37..a9b8581 100644 --- a/src/schedulables_tree_widget.hh +++ b/src/schedulables_tree_widget.hh @@ -88,6 +88,13 @@ namespace sgpem void _on_add_thread(); void _on_add_request(); + void _on_edit_process(); + void _on_edit_thread(); + void _on_edit_request(); + + void add_edit_process(bool adding); + void add_edit_thread(bool adding); + void _on_remove_process(); void _on_remove_thread(); void _on_remove_request();