diff options
Diffstat (limited to 'src/gui/LoadPluginWindow.cpp')
-rw-r--r-- | src/gui/LoadPluginWindow.cpp | 511 |
1 files changed, 0 insertions, 511 deletions
diff --git a/src/gui/LoadPluginWindow.cpp b/src/gui/LoadPluginWindow.cpp deleted file mode 100644 index bd08f457..00000000 --- a/src/gui/LoadPluginWindow.cpp +++ /dev/null @@ -1,511 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2017 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string> - -#include <stddef.h> - -#include <cassert> -#include <algorithm> - -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "LoadPluginWindow.hpp" -#include "GraphCanvas.hpp" -#include "GraphView.hpp" -#include "GraphWindow.hpp" - -#include "ingen_config.h" - -using std::string; - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, - const Glib::RefPtr<Gtk::Builder>& xml) - : Window(cobject) - , _name_offset(0) - , _has_shown(false) - , _refresh_list(true) -{ - xml->get_widget("load_plugin_plugins_treeview", _plugins_treeview); - xml->get_widget("load_plugin_polyphonic_checkbutton", _polyphonic_checkbutton); - xml->get_widget("load_plugin_name_entry", _name_entry); - xml->get_widget("load_plugin_add_button", _add_button); - xml->get_widget("load_plugin_close_button", _close_button); - - xml->get_widget("load_plugin_filter_combo", _filter_combo); - xml->get_widget("load_plugin_search_entry", _search_entry); - - // Set up the plugins list - _plugins_liststore = Gtk::ListStore::create(_plugins_columns); - _plugins_treeview->set_model(_plugins_liststore); - _plugins_treeview->append_column("_Name", _plugins_columns._col_name); - _plugins_treeview->append_column("_Type", _plugins_columns._col_type); - _plugins_treeview->append_column("_Project", _plugins_columns._col_project); - _plugins_treeview->append_column("_Author", _plugins_columns._col_author); - _plugins_treeview->append_column("_URI", _plugins_columns._col_uri); - - // This could be nicer.. store the TreeViewColumns locally maybe? - _plugins_treeview->get_column(0)->set_sort_column(_plugins_columns._col_name); - _plugins_treeview->get_column(1)->set_sort_column(_plugins_columns._col_type); - _plugins_treeview->get_column(2)->set_sort_column(_plugins_columns._col_project); - _plugins_treeview->get_column(2)->set_sort_column(_plugins_columns._col_author); - _plugins_treeview->get_column(3)->set_sort_column(_plugins_columns._col_uri); - for (int i = 0; i < 5; ++i) { - _plugins_treeview->get_column(i)->set_resizable(true); - } - - // Set up the search criteria combobox - _criteria_liststore = Gtk::ListStore::create(_criteria_columns); - _filter_combo->set_model(_criteria_liststore); - - Gtk::TreeModel::iterator iter = _criteria_liststore->append(); - Gtk::TreeModel::Row row = *iter; - row[_criteria_columns._col_label] = "Name contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::NAME; - _filter_combo->set_active(iter); - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "Type contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::TYPE; - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "Project contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::PROJECT; - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "Author contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::AUTHOR; - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "URI contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::URI; - _filter_combo->pack_start(_criteria_columns._col_label); - - _add_button->signal_clicked().connect( - sigc::mem_fun(this, &LoadPluginWindow::add_clicked)); - _close_button->signal_clicked().connect( - sigc::mem_fun(this, &Window::hide)); - _plugins_treeview->signal_row_activated().connect( - sigc::mem_fun(this, &LoadPluginWindow::plugin_activated)); - _search_entry->signal_activate().connect( - sigc::mem_fun(this, &LoadPluginWindow::add_clicked)); - _search_entry->signal_changed().connect( - sigc::mem_fun(this, &LoadPluginWindow::filter_changed)); - _name_entry->signal_changed().connect( - sigc::mem_fun(this, &LoadPluginWindow::name_changed)); - - _search_entry->signal_icon_release().connect( - sigc::mem_fun(this, &LoadPluginWindow::name_cleared)); - - _selection = _plugins_treeview->get_selection(); - _selection->set_mode(Gtk::SELECTION_MULTIPLE); - _selection->signal_changed().connect( - sigc::mem_fun(this, &LoadPluginWindow::plugin_selection_changed)); - - //m_add_button->grab_default(); -} - -void -LoadPluginWindow::present(SPtr<const GraphModel> graph, - Properties data) -{ - set_graph(graph); - _initial_data = data; - Gtk::Window::present(); -} - -/** Called every time the user types into the name input box. - * Used to display warning messages, and enable/disable the OK button. - */ -void -LoadPluginWindow::name_changed() -{ - // Toggle add button sensitivity according name legality - if (_selection->get_selected_rows().size() == 1) { - const string sym = _name_entry->get_text(); - if (!Raul::Symbol::is_valid(sym)) { - _add_button->property_sensitive() = false; - } else if (_app->store()->find(_graph->path().child(Raul::Symbol(sym))) - != _app->store()->end()) { - _add_button->property_sensitive() = false; - } else { - _add_button->property_sensitive() = true; - } - } -} - -void -LoadPluginWindow::name_cleared(Gtk::EntryIconPosition pos, const GdkEventButton* event) -{ - _search_entry->set_text(""); -} - -/** Sets the graph controller for this window and initializes everything. - * - * This function MUST be called before using the window in any way! - */ -void -LoadPluginWindow::set_graph(SPtr<const GraphModel> graph) -{ - if (_graph) { - _graph = graph; - plugin_selection_changed(); - } else { - _graph = graph; - } -} - -/** Populates the plugin list on the first show. - * - * This is done here instead of construction time as the list population is - * really expensive and bogs down creation of a graph. This is especially - * important when many graph notifications are sent at one time from the - * engine. - */ -void -LoadPluginWindow::on_show() -{ - if (!_has_shown) { - _app->store()->signal_new_plugin().connect( - sigc::mem_fun(this, &LoadPluginWindow::add_plugin)); - _has_shown = true; - } - - if (_refresh_list) { - set_plugins(_app->store()->plugins()); - _refresh_list = false; - } - - Gtk::Window::on_show(); -} - -void -LoadPluginWindow::set_plugins(SPtr<const ClientStore::Plugins> plugins) -{ - _rows.clear(); - _plugins_liststore->clear(); - - for (const auto& p : *plugins.get()) { - add_plugin(p.second); - } - - _plugins_liststore->set_sort_column(1, Gtk::SORT_ASCENDING); - _plugins_treeview->columns_autosize(); -} - -void -LoadPluginWindow::new_plugin(SPtr<const PluginModel> pm) -{ - if (is_visible()) { - add_plugin(pm); - } else { - _refresh_list = true; - } -} - -static std::string -get_project_name(SPtr<const PluginModel> plugin) -{ - std::string name; - if (plugin->lilv_plugin()) { - LilvNode* project = lilv_plugin_get_project(plugin->lilv_plugin()); - if (!project) { - return ""; - } - - LilvNode* doap_name = lilv_new_uri( - plugin->lilv_world(), "http://usefulinc.com/ns/doap#name"); - LilvNodes* names = lilv_world_find_nodes( - plugin->lilv_world(), project, doap_name, nullptr); - - if (names) { - name = lilv_node_as_string(lilv_nodes_get_first(names)); - } - - lilv_nodes_free(names); - lilv_node_free(doap_name); - lilv_node_free(project); - } - return name; -} - -static std::string -get_author_name(SPtr<const PluginModel> plugin) -{ - std::string name; - if (plugin->lilv_plugin()) { - LilvNode* author = lilv_plugin_get_author_name(plugin->lilv_plugin()); - if (author) { - name = lilv_node_as_string(author); - } - lilv_node_free(author); - } - return name; -} - -void -LoadPluginWindow::set_row(Gtk::TreeModel::Row& row, - SPtr<const PluginModel> plugin) -{ - const URIs& uris = _app->uris(); - const Atom& name = plugin->get_property(uris.doap_name); - if (name.is_valid() && name.type() == uris.forge.String) { - row[_plugins_columns._col_name] = name.ptr<char>(); - } - - if (uris.lv2_Plugin == plugin->type()) { - row[_plugins_columns._col_type] = lilv_node_as_string( - lilv_plugin_class_get_label( - lilv_plugin_get_class(plugin->lilv_plugin()))); - - row[_plugins_columns._col_project] = get_project_name(plugin); - row[_plugins_columns._col_author] = get_author_name(plugin); - } else if (uris.ingen_Internal == plugin->type()) { - row[_plugins_columns._col_type] = "Internal"; - row[_plugins_columns._col_project] = "Ingen"; - row[_plugins_columns._col_author] = "David Robillard"; - } else if (uris.ingen_Graph == plugin->type()) { - row[_plugins_columns._col_type] = "Graph"; - } else { - row[_plugins_columns._col_type] = ""; - } - - row[_plugins_columns._col_uri] = plugin->uri().string(); - row[_plugins_columns._col_plugin] = plugin; -} - -void -LoadPluginWindow::add_plugin(SPtr<const PluginModel> plugin) -{ - if (plugin->lilv_plugin() && lilv_plugin_is_replaced(plugin->lilv_plugin())) { - return; - } - - Gtk::TreeModel::iterator iter = _plugins_liststore->append(); - Gtk::TreeModel::Row row = *iter; - _rows.emplace(plugin->uri(), iter); - - set_row(row, plugin); - - plugin->signal_property().connect( - sigc::bind<0>(sigc::mem_fun(this, &LoadPluginWindow::plugin_property_changed), - plugin->uri())); -} - -///// Event Handlers ////// - -void -LoadPluginWindow::plugin_activated(const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn* col) -{ - add_clicked(); -} - -void -LoadPluginWindow::plugin_selection_changed() -{ - size_t n_selected = _selection->get_selected_rows().size(); - if (n_selected == 0) { - _name_offset = 0; - _name_entry->set_text(""); - _name_entry->set_sensitive(false); - } else if (n_selected == 1) { - Gtk::TreeModel::iterator iter = _plugins_liststore->get_iter( - *_selection->get_selected_rows().begin()); - if (iter) { - Gtk::TreeModel::Row row = *iter; - SPtr<const PluginModel> p = row.get_value( - _plugins_columns._col_plugin); - _name_offset = _app->store()->child_name_offset( - _graph->path(), p->default_block_symbol()); - _name_entry->set_text(generate_module_name(p, _name_offset)); - _name_entry->set_sensitive(true); - } else { - _name_offset = 0; - _name_entry->set_text(""); - _name_entry->set_sensitive(false); - } - } else { - _name_entry->set_text(""); - _name_entry->set_sensitive(false); - } -} - -/** Generate an automatic name for this Node. - * - * Offset is an offset of the number that will be appended to the plugin's - * label, needed if the user adds multiple plugins faster than the engine - * sends the notification back. - */ -string -LoadPluginWindow::generate_module_name(SPtr<const PluginModel> plugin, - int offset) -{ - std::stringstream ss; - ss << plugin->default_block_symbol(); - if (offset != 0) { - ss << "_" << offset; - } - return ss.str(); -} - -void -LoadPluginWindow::load_plugin(const Gtk::TreeModel::iterator& iter) -{ - const URIs& uris = _app->uris(); - Gtk::TreeModel::Row row = *iter; - SPtr<const PluginModel> plugin = row.get_value(_plugins_columns._col_plugin); - bool polyphonic = _polyphonic_checkbutton->get_active(); - string name = _name_entry->get_text(); - - if (name.empty()) { - name = generate_module_name(plugin, _name_offset); - } - - if (name.empty() || !Raul::Symbol::is_valid(name)) { - Gtk::MessageDialog dialog( - *this, - "Unable to choose a default name, please provide one", - false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - - dialog.run(); - } else { - Raul::Path path = _graph->path().child(Raul::Symbol::symbolify(name)); - Properties props = _initial_data; - props.emplace(uris.rdf_type, Property(uris.ingen_Block)); - props.emplace(uris.lv2_prototype, _app->forge().make_urid(plugin->uri())); - props.emplace(uris.ingen_polyphonic, _app->forge().make(polyphonic)); - _app->interface()->put(path_to_uri(path), props); - - if (_selection->get_selected_rows().size() == 1) { - _name_offset = (_name_offset == 0) ? 2 : _name_offset + 1; - _name_entry->set_text(generate_module_name(plugin, _name_offset)); - } - - // Cascade next block - Atom& x = _initial_data.find(uris.ingen_canvasX)->second; - x = _app->forge().make(x.get<float>() + 20.0f); - Atom& y = _initial_data.find(uris.ingen_canvasY)->second; - y = _app->forge().make(y.get<float>() + 20.0f); - } -} - -void -LoadPluginWindow::add_clicked() -{ - _selection->selected_foreach_iter( - sigc::mem_fun(*this, &LoadPluginWindow::load_plugin)); -} - -void -LoadPluginWindow::filter_changed() -{ - _rows.clear(); - _plugins_liststore->clear(); - string search = _search_entry->get_text(); - transform(search.begin(), search.end(), search.begin(), ::toupper); - - // Get selected criteria - const Gtk::TreeModel::Row row = *(_filter_combo->get_active()); - CriteriaColumns::Criteria criteria = row[_criteria_columns._col_criteria]; - - string field; - - Gtk::TreeModel::Row model_row; - Gtk::TreeModel::iterator model_iter; - size_t num_visible = 0; - const URIs& uris = _app->uris(); - - for (const auto& p : *_app->store()->plugins().get()) { - const SPtr<PluginModel> plugin = p.second; - const Atom& name = plugin->get_property(uris.doap_name); - - switch (criteria) { - case CriteriaColumns::Criteria::NAME: - if (name.is_valid() && name.type() == uris.forge.String) { - field = name.ptr<char>(); - } - break; - case CriteriaColumns::Criteria::TYPE: - if (plugin->lilv_plugin()) { - field = lilv_node_as_string( - lilv_plugin_class_get_label( - lilv_plugin_get_class(plugin->lilv_plugin()))); - } - break; - case CriteriaColumns::Criteria::PROJECT: - field = get_project_name(plugin); - break; - case CriteriaColumns::Criteria::AUTHOR: - field = get_author_name(plugin); - break; - case CriteriaColumns::Criteria::URI: - field = plugin->uri(); - break; - } - - transform(field.begin(), field.end(), field.begin(), ::toupper); - - if (field.find(search) != string::npos) { - model_iter = _plugins_liststore->append(); - model_row = *model_iter; - set_row(model_row, plugin); - ++num_visible; - } - } - - if (num_visible == 1) { - _selection->unselect_all(); - _selection->select(model_iter); - } -} - -bool -LoadPluginWindow::on_key_press_event(GdkEventKey* event) -{ - if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { - hide(); - return true; - } else { - return Gtk::Window::on_key_press_event(event); - } -} - -void -LoadPluginWindow::plugin_property_changed(const URI& plugin, - const URI& predicate, - const Atom& value) -{ - const URIs& uris = _app->uris(); - if (predicate == uris.doap_name) { - Rows::const_iterator i = _rows.find(plugin); - if (i != _rows.end() && value.type() == uris.forge.String) { - (*i->second)[_plugins_columns._col_name] = value.ptr<char>(); - } - } -} - -} // namespace GUI -} // namespace Ingen |