// -*- Mode: C++ ; indent-tabs-mode: t -*- /* This file is part of Patchage. * Copyright (C) 2008 Nedko Arnaudov * * Patchage 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 2 of the License, or (at your option) any later * version. * * Patchage 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 details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include "ProjectList.hpp" #include "Widget.hpp" #include "Session.hpp" #include "Project.hpp" #include "ProjectPropertiesDialog.hpp" #include "LashClient.hpp" #include "LashProxy.hpp" using boost::shared_ptr; using namespace std; struct ProjectList_column_record : public Gtk::TreeModel::ColumnRecord { Gtk::TreeModelColumn name; Gtk::TreeModelColumn< shared_ptr > project; }; struct ProjectListImpl : public sigc::trackable { Patchage* _app; Widget _widget; ProjectList_column_record _columns; Glib::RefPtr _model; Gtk::Menu _menu_popup; ProjectListImpl( Glib::RefPtr xml, Patchage* app); void project_added(shared_ptr project); void project_closed(shared_ptr project); void project_renamed(Gtk::TreeModel::iterator iter); void client_added(shared_ptr client, Gtk::TreeModel::iterator iter); void client_removed(shared_ptr client, Gtk::TreeModel::iterator iter); bool on_button_press_event(GdkEventButton * event); void on_menu_popup_load_project(); void on_menu_popup_save_all_projects(); void on_menu_popup_save_project(shared_ptr project); void on_menu_popup_close_project(shared_ptr project); void on_menu_popup_project_properties(shared_ptr project); void on_menu_popup_close_all_projects(); }; ProjectList::ProjectList( Patchage* app, Session* session) { _impl = new ProjectListImpl(app->xml(), app); session->_signal_project_added.connect(mem_fun(_impl, &ProjectListImpl::project_added)); session->_signal_project_closed.connect(mem_fun(_impl, &ProjectListImpl::project_closed)); } ProjectList::~ProjectList() { delete _impl; } ProjectListImpl::ProjectListImpl(Glib::RefPtr xml, Patchage* app) : _app(app) , _widget(xml, "projects_list") { _columns.add(_columns.name); _columns.add(_columns.project); _model = Gtk::TreeStore::create(_columns); _widget->set_model(_model); _widget->append_column("LASH projects", _columns.name); _menu_popup.accelerate(*_widget); _widget->signal_button_press_event().connect(sigc::mem_fun(*this, &ProjectListImpl::on_button_press_event), false); } bool ProjectListImpl::on_button_press_event(GdkEventButton* event) { // Then do our custom stuff: if (event->type == GDK_BUTTON_PRESS && event->button == 3) { Glib::RefPtr selection = _widget->get_selection(); Gtk::TreeModel::Path path; Gtk::TreeViewColumn * column_ptr; int cell_x; int cell_y; Gtk::Menu::MenuList& menulist = _menu_popup.items(); menulist.clear(); menulist.push_back(Gtk::Menu_Helpers::MenuElem("_Load project...", sigc::mem_fun(*this, &ProjectListImpl::on_menu_popup_load_project))); menulist.push_back(Gtk::Menu_Helpers::MenuElem("Save _all projects", sigc::mem_fun(*this, &ProjectListImpl::on_menu_popup_save_all_projects))); if (_widget->get_path_at_pos((int)event->x, (int)event->y, path, column_ptr, cell_x, cell_y)) { //cout << path.to_string() << endl; selection->unselect_all(); selection->select(path); Gtk::TreeIter iter = selection->get_selected(); shared_ptr project = (*iter)[_columns.project]; if (project) { const string& name = project->get_name(); menulist.push_back(Gtk::Menu_Helpers::MenuElem( (string)"_Save project '" + name + "'", sigc::bind( sigc::mem_fun(*this, &ProjectListImpl::on_menu_popup_save_project), project))); menulist.push_back(Gtk::Menu_Helpers::MenuElem( (string)"_Close project '" + name + "'", sigc::bind( sigc::mem_fun(*this, &ProjectListImpl::on_menu_popup_close_project), project))); menulist.push_back(Gtk::Menu_Helpers::MenuElem( (string)"_Project '" + name + "' properties", sigc::bind( sigc::mem_fun(*this, &ProjectListImpl::on_menu_popup_project_properties), project))); } } else { //cout << "No row" << endl; selection->unselect_all(); } menulist.push_back(Gtk::Menu_Helpers::MenuElem("Cl_ose all projects", sigc::mem_fun(*this, &ProjectListImpl::on_menu_popup_close_all_projects))); _menu_popup.popup(event->button, event->time); return true; } return false; } void ProjectListImpl::on_menu_popup_load_project() { _app->show_load_project_dialog(); } void ProjectListImpl::on_menu_popup_save_all_projects() { _app->lash_proxy()->save_all_projects(); } void ProjectListImpl::on_menu_popup_save_project(shared_ptr project) { _app->lash_proxy()->save_project(project->get_name()); } void ProjectListImpl::on_menu_popup_close_project(shared_ptr project) { _app->lash_proxy()->close_project(project->get_name()); } void ProjectListImpl::on_menu_popup_project_properties(shared_ptr project) { ProjectPropertiesDialog dialog(_app->xml()); dialog.run(project); } void ProjectListImpl::on_menu_popup_close_all_projects() { _app->lash_proxy()->close_all_projects(); } void ProjectListImpl::project_added( shared_ptr project) { Gtk::TreeModel::iterator iter; Gtk::TreeModel::iterator child_iter; Gtk::TreeModel::Row row; string project_name = project->get_name(); if (project->get_modified_status()) { project_name += " *"; } iter = _model->append(); row = *iter; row[_columns.name] = project_name; row[_columns.project] = project; project->_signal_renamed.connect( bind(mem_fun(this, &ProjectListImpl::project_renamed), iter)); project->_signal_modified_status_changed.connect( bind(mem_fun(this, &ProjectListImpl::project_renamed), iter)); project->_signal_client_added.connect( bind(mem_fun(this, &ProjectListImpl::client_added), iter)); project->_signal_client_removed.connect( bind(mem_fun(this, &ProjectListImpl::client_removed), iter)); } void ProjectListImpl::project_closed( shared_ptr project) { shared_ptr temp_project; Gtk::TreeModel::Children children = _model->children(); Gtk::TreeModel::Children::iterator iter = children.begin(); while (iter != children.end()) { Gtk::TreeModel::Row row = *iter; temp_project = row[_columns.project]; if (temp_project == project) { _model->erase(iter); return; } iter++; } } void ProjectListImpl::project_renamed( Gtk::TreeModel::iterator iter) { shared_ptr project; Gtk::TreeModel::Row row = *iter; project = row[_columns.project]; string project_name = project->get_name(); if (project->get_modified_status()) project_name += " *"; row[_columns.name] = project_name; } void ProjectListImpl::client_added( shared_ptr client, Gtk::TreeModel::iterator iter) { Gtk::TreeModel::Path path = _model->get_path(iter); Gtk::TreeModel::Row row = *iter; iter = _model->append(row.children()); row = *iter; row[_columns.name] = client->get_name(); _widget->expand_row(path, false); } void ProjectListImpl::client_removed( shared_ptr client, Gtk::TreeModel::iterator iter) { if (!iter) return; Gtk::TreeModel::Path path = _model->get_path(iter); Gtk::TreeModel::Row row = *iter; Gtk::TreeNodeChildren childs = row.children(); for (Gtk::TreeModel::iterator child_iter = childs.begin(); child_iter; child_iter++) { row = *child_iter; if (row[_columns.name] == client->get_name()) { _widget->expand_row(path, false); _model->erase(child_iter); return; } } } void ProjectList::set_lash_available(bool lash_active) { _impl->_widget->set_sensitive(lash_active); }