diff options
author | waker <wakeroid@gmail.com> | 2012-10-05 17:46:33 +0200 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2012-10-05 17:46:33 +0200 |
commit | ce2923c8f0cac7a563d1ecf22085ac62281c74d7 (patch) | |
tree | 20ce1a2fd0cebc36231882b011e34230778a1db9 /plugins/shellexecui/shellexecui.c | |
parent | 527ba48d8209a8e854c791d571106a5daf2fdd29 (diff) | |
parent | 708c8ba9f7aefe9f795c9c4eb30ab128f09c8b3d (diff) |
Merge branch 'master' into devel
Conflicts:
README
configure.ac
deadbeef.h
plugins.c
plugins/gtkui/Makefile.am
plugins/gtkui/ddbcellrenderertextmultiline.c
plugins/gtkui/ddblistview.c
plugins/gtkui/deadbeef.glade
plugins/gtkui/gtkui.c
plugins/gtkui/interface.c
plugins/gtkui/plcommon.c
plugins/shellexec/shellexec.c
plugins/supereq/Makefile.am
Diffstat (limited to 'plugins/shellexecui/shellexecui.c')
-rw-r--r-- | plugins/shellexecui/shellexecui.c | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/plugins/shellexecui/shellexecui.c b/plugins/shellexecui/shellexecui.c new file mode 100644 index 00000000..b2a60230 --- /dev/null +++ b/plugins/shellexecui/shellexecui.c @@ -0,0 +1,443 @@ +/* + Copyright (C) 2012 Azeem Arshad <kr00r4n@gmail.com> + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include <stdlib.h> +#include <string.h> +#include <gtk/gtk.h> +#include "interface.h" +#include "callbacks.h" +#include "support.h" +#include "../../deadbeef.h" +#include "../gtkui/gtkui_api.h" +#include "../shellexec/shellexec.h" + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } + +DB_functions_t *deadbeef; +static DB_misc_t plugin; +static ddb_gtkui_t *gtkui_plugin; +static Shx_plugin_t *shellexec_plugin; + +static Shx_action_t *actions; // list of actions being edited +static GtkWidget *conf_dlg; +static GtkWidget *edit_dlg; +static Shx_action_t *current_action; // selection action when edit window is active + +enum { + COL_TITLE = 0, + COL_META, + COL_COUNT, +}; + +static int +name_exists(const char *name, Shx_action_t *skip) { + DB_plugin_t **p = deadbeef->plug_get_list (); + for (int i = 0; p[i]; i++) { + if (!p[i]->get_actions) { + continue; + } + DB_plugin_action_t *action = p[i]->get_actions (NULL); + while(action) { + if(action != (DB_plugin_action_t*)skip && action->name && !strcmp(action->name, name)) { + return 1; + } + action = action->next; + } + } + return 0; +} + +static int +is_empty(const char *name) { + char *p = (char *)name; + while(*p) { + if(*p != ' ' || *p != '\t') { + return 0; + } + p++; + } + return 1; +} + +void +on_save_button_clicked (GtkButton *button, + gpointer user_data) { + gtk_widget_destroy(conf_dlg); +} + +GtkWidget *create_edit_dlg() { + GtkWidget *dlg = create_shellexec_conf_edit_dialog(); + gtk_window_set_transient_for(GTK_WINDOW(dlg), + GTK_WINDOW(conf_dlg)); + return dlg; +} + +void +on_add_button_clicked (GtkButton *button, + gpointer user_data) { + current_action = NULL; + edit_dlg = create_edit_dlg(); + gtk_window_set_title(GTK_WINDOW(edit_dlg), _("Add Command")); + + // generate unique command name + char name[15] = "new_cmd"; + int suffix = 0; + while(name_exists(name, NULL) && suffix < 1000) { // create a unique name + snprintf(name, sizeof (name), "new_cmd%d", suffix); + suffix++; + } + if (name_exists (name, NULL)) { + return; + } + // Set default values in text fields + gtk_entry_set_text( + GTK_ENTRY(lookup_widget(edit_dlg, "name_entry")), + name); + gtk_entry_set_text( + GTK_ENTRY(lookup_widget(edit_dlg, "title_entry")), + "New Command"); + + // Set default values in check boxes + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "single_check")), + TRUE); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "local_check")), + TRUE); + + gtk_widget_show(edit_dlg); +} + +void +on_remove_button_clicked (GtkButton *button, + gpointer user_data) { + GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget(conf_dlg, "command_treeview")); + GtkTreeModel *treemodel = gtk_tree_view_get_model(treeview); + GtkTreeIter iter; + GtkTreeSelection *selection; + selection = gtk_tree_view_get_selection(treeview); + if(gtk_tree_selection_get_selected(selection, &treemodel, &iter)) { + // ask confirmation + GtkWidget *confirm_dlg = gtk_message_dialog_new (GTK_WINDOW(conf_dlg), GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, + _("Delete")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (confirm_dlg), + "%s", _("This action will delete the selected shell command. Are you sure?")); + gtk_window_set_transient_for(GTK_WINDOW (confirm_dlg), GTK_WINDOW (conf_dlg)); + gtk_window_set_title (GTK_WINDOW (confirm_dlg), _("Confirm Remove")); + int response = gtk_dialog_run (GTK_DIALOG (confirm_dlg)); + gtk_widget_destroy(confirm_dlg); + if(response == GTK_RESPONSE_NO) { + return; + } + + Shx_action_t *action; + gtk_tree_model_get(treemodel, &iter, COL_META, &action, -1); + + //remove action from list + shellexec_plugin->action_remove (action); + actions = (Shx_action_t *)shellexec_plugin->misc.plugin.get_actions(NULL); + + GtkTreeIter next_iter = iter; + if(gtk_tree_model_iter_next(treemodel, &next_iter)) { + gtk_tree_selection_select_iter(selection, &next_iter); + } + else { + int count = gtk_tree_model_iter_n_children(treemodel, NULL); + if(count >= 2) { + GtkTreePath *last = gtk_tree_path_new_from_indices(count-2, -1); + gtk_tree_selection_select_path(selection, last); + } + } + gtk_list_store_remove(GTK_LIST_STORE(treemodel), &iter); + + shellexec_plugin->save_actions(); + deadbeef->sendmessage (DB_EV_ACTIONSCHANGED, 0, 0, 0); + } +} + +void +on_edit_button_clicked(GtkButton *button, gpointer user_data) { + GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget(conf_dlg, "command_treeview")); + GtkTreeModel *treemodel = gtk_tree_view_get_model(treeview); + GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); + GtkTreeIter iter; + if(gtk_tree_selection_get_selected(selection, &treemodel, &iter)) { + gtk_tree_model_get(treemodel, &iter, COL_META, ¤t_action, -1); + edit_dlg = create_edit_dlg(); + // Set text fields + gtk_entry_set_text( + GTK_ENTRY(lookup_widget(edit_dlg, "name_entry")), + current_action->parent.name); + gtk_entry_set_text( + GTK_ENTRY(lookup_widget(edit_dlg, "title_entry")), + current_action->parent.title); + gtk_entry_set_text( + GTK_ENTRY(lookup_widget(edit_dlg, "cmd_entry")), + current_action->shcommand); + + // Set check boxes + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "single_check")), + current_action->parent.flags & DB_ACTION_SINGLE_TRACK); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "multiple_check")), + current_action->parent.flags & DB_ACTION_ALLOW_MULTIPLE_TRACKS); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "playlist_check")), + current_action->parent.flags & DB_ACTION_PLAYLIST); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "local_check")), + current_action->shx_flags & SHX_ACTION_LOCAL_ONLY); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "remote_check")), + current_action->shx_flags & SHX_ACTION_REMOTE_ONLY); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "common_check")), + current_action->parent.flags & DB_ACTION_COMMON); + + gtk_widget_show(edit_dlg); + } +} + +void +on_edit_cancel_button_clicked (GtkButton *button, gpointer user_data) { + gtk_widget_destroy(edit_dlg); +} + +static int +validate_command_edit () { + const char *text; + char message[256] = ""; + int valid = 1; + + text = gtk_entry_get_text(GTK_ENTRY(lookup_widget(edit_dlg, "name_entry"))); + if(is_empty(text) || name_exists(text, current_action)) { + strcat(message, _("ID must be non-empty and unique.\n")); + valid = 0; + } + + text = gtk_entry_get_text(GTK_ENTRY(lookup_widget(edit_dlg, "title_entry"))); + if(is_empty(text)) { + strcat(message, _("Title must be non-empty.\n")); + valid = 0; + } + + text = gtk_entry_get_text(GTK_ENTRY(lookup_widget(edit_dlg, "cmd_entry"))); + if(is_empty(text)) { + strcat(message, _("Shell Command must be non-empty.\n")); + valid = 0; + } + + if(!valid) { + GtkWidget *invalid_dlg = gtk_message_dialog_new (GTK_WINDOW(conf_dlg), GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + _("Invalid Values")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (invalid_dlg), + "%s", message); + gtk_window_set_transient_for(GTK_WINDOW (invalid_dlg), GTK_WINDOW (conf_dlg)); + gtk_window_set_title (GTK_WINDOW (invalid_dlg), _("Invalid Values")); + gtk_dialog_run (GTK_DIALOG (invalid_dlg)); + gtk_widget_destroy(invalid_dlg); + } + return valid; +} + +void +on_edit_ok_button_clicked (GtkButton *button, gpointer user_data) { + if(!validate_command_edit()) { + return; + } + // Update the main window tree view + GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget(conf_dlg, "command_treeview")); + GtkTreeModel *treemodel = gtk_tree_view_get_model(treeview); + GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); + GtkTreeIter iter; + + if(current_action == NULL) { + current_action = shellexec_plugin->action_add (); + actions = (Shx_action_t *)shellexec_plugin->misc.plugin.get_actions(NULL); + gtk_list_store_append(GTK_LIST_STORE(treemodel), &iter); + gtk_list_store_set(GTK_LIST_STORE(treemodel), &iter, COL_META, current_action, -1); + gtk_tree_selection_select_iter(selection, &iter); + } + else { + gtk_tree_selection_get_selected(selection, &treemodel, &iter); + } + // Store all the text fields in the current action + GtkEntry *entry; + entry = GTK_ENTRY(lookup_widget(edit_dlg, "name_entry")); + current_action->parent.name = strdup(gtk_entry_get_text(entry)); + entry = GTK_ENTRY(lookup_widget(edit_dlg, "title_entry")); + current_action->parent.title = strdup(gtk_entry_get_text(entry)); + entry = GTK_ENTRY(lookup_widget(edit_dlg, "cmd_entry")); + current_action->shcommand = strdup(gtk_entry_get_text(entry)); + + gboolean active; + int flags = current_action->parent.flags; + int shx_flags = current_action->shx_flags; + // Store all the check button values in the current action + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "single_check"))); + flags = (flags & ~DB_ACTION_SINGLE_TRACK) | (active?DB_ACTION_SINGLE_TRACK:0); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "multiple_check"))); + flags = (flags & ~DB_ACTION_ALLOW_MULTIPLE_TRACKS) | (active?DB_ACTION_ALLOW_MULTIPLE_TRACKS:0); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "playlist_check"))); + flags = (flags & ~DB_ACTION_PLAYLIST) | (active?DB_ACTION_PLAYLIST:0); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "local_check"))); + shx_flags = (shx_flags & ~SHX_ACTION_LOCAL_ONLY) | (active?SHX_ACTION_LOCAL_ONLY:0); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "remote_check"))); + shx_flags = (shx_flags & ~SHX_ACTION_REMOTE_ONLY) | (active?SHX_ACTION_REMOTE_ONLY:0); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(edit_dlg, "common_check"))); + flags = (flags & ~DB_ACTION_COMMON) | (active?DB_ACTION_COMMON:0); + + current_action->parent.flags = flags; + current_action->shx_flags = shx_flags; + + gtk_list_store_set(GTK_LIST_STORE(treemodel), &iter, + COL_TITLE, current_action->parent.title, -1); + + gtk_widget_destroy(edit_dlg); + edit_dlg = NULL; + current_action = NULL; + + shellexec_plugin->save_actions(); + deadbeef->sendmessage (DB_EV_ACTIONSCHANGED, 0, 0, 0); +} + +static void +init_treeview() { + // Create the tree view and cell renderers + GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget(conf_dlg, "command_treeview")); + GtkCellRenderer *cell_renderer; + cell_renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Title"), cell_renderer, + "text", COL_TITLE, NULL); + + // Create the tree view data model and fill it with values + GtkListStore *liststore; + liststore = gtk_list_store_new(COL_COUNT, + G_TYPE_STRING, + //G_TYPE_BOOLEAN, + G_TYPE_POINTER); + actions = (Shx_action_t *)shellexec_plugin->misc.plugin.get_actions(NULL); + Shx_action_t *action = actions; + GtkTreeIter iter; + while(action) { + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, + COL_TITLE, action->parent.title, + COL_META, action, -1); + action = (Shx_action_t *)action->parent.next; + } + + gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(liststore)); + g_object_unref(liststore); +} + +static gboolean +shellexecui_action_gtk (void *data) +{ + conf_dlg = create_shellexec_conf_dialog(); + gtk_widget_set_size_request (conf_dlg, 400, 400); + gtk_window_set_transient_for(GTK_WINDOW(conf_dlg), + GTK_WINDOW(gtkui_plugin->get_mainwin())); + init_treeview(); + gtk_widget_show(conf_dlg); + return FALSE; +} + +static int +shellexecui_action_callback(DB_plugin_action_t *action, + void *user_data) { + g_idle_add (shellexecui_action_gtk, NULL); + return 0; +} + +static DB_plugin_action_t shellexecui_action = { + .title = "Edit/Configure custom shell commands", + .name = "shellexec_conf", + .flags = DB_ACTION_COMMON, + .callback = shellexecui_action_callback, + .next = NULL, +}; + +static DB_plugin_action_t * +shxui_getactions(DB_playItem_t *it) { + return &shellexecui_action; +} + +int shxui_connect() { +#if GTK_CHECK_VERSION(3,0,0) + gtkui_plugin = (ddb_gtkui_t *)deadbeef->plug_get_for_id ("gtkui3"); +#else + gtkui_plugin = (ddb_gtkui_t *)deadbeef->plug_get_for_id ("gtkui"); +#endif + shellexec_plugin = (Shx_plugin_t *)deadbeef->plug_get_for_id ("shellexec"); + if(!gtkui_plugin || !shellexec_plugin) { + return -1; + } + if(shellexec_plugin->misc.plugin.version_major == 1 && + shellexec_plugin->misc.plugin.version_minor < 1) { + return -1; + } + return 0; +} + +static DB_misc_t plugin = { + .plugin.type = DB_PLUGIN_MISC, + .plugin.api_vmajor = 1, + .plugin.api_vminor = 0, + .plugin.version_major = 1, + .plugin.version_minor = 0, +#if GTK_CHECK_VERSION(3,0,0) + .plugin.id = "shellexecui_gtk3", + .plugin.name = "Shellexec GTK3 UI", +#else + .plugin.id = "shellexecui_gtk2", + .plugin.name = "Shellexec GTK2 UI", +#endif + .plugin.descr = "A GTK UI for the Shellexec plugin", + .plugin.copyright = + "Copyright (C) 2012 Azeem Arshad <kr00r4n@gmail.com>\n" + "\n" + "This program is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU General Public License\n" + "as published by the Free Software Foundation; either version 2\n" + "of the License, or (at your option) any later version.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program; if not, write to the Free Software\n" + "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n", + .plugin.website = "http://azeemarshad.in", + .plugin.get_actions = shxui_getactions, + .plugin.connect = shxui_connect, +}; + +DB_plugin_t * +#if GTK_CHECK_VERSION(3,0,0) +shellexecui_gtk3_load (DB_functions_t *api) { +#else +shellexecui_gtk2_load (DB_functions_t *api) { +#endif + deadbeef = api; + return DB_PLUGIN(&plugin); +} |