summaryrefslogtreecommitdiffstats
path: root/gtk/src/queuehandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/src/queuehandler.c')
-rw-r--r--gtk/src/queuehandler.c525
1 files changed, 517 insertions, 8 deletions
diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c
index 507b3cc08..847eacd6d 100644
--- a/gtk/src/queuehandler.c
+++ b/gtk/src/queuehandler.c
@@ -680,8 +680,8 @@ validate_settings(signal_user_data_t *ud, GValue *settings, gint batch)
return TRUE;
}
-gboolean
-ghb_queue_add(signal_user_data_t *ud, GValue *settings, gint batch)
+static gboolean
+queue_add(signal_user_data_t *ud, GValue *settings, gint batch)
{
// Add settings to the queue
gint titleindex;
@@ -720,17 +720,526 @@ queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
{
g_debug("queue_add_clicked_cb ()");
GValue *settings = ghb_value_dup(ud->settings);
- if (!ghb_queue_add(ud, settings, 0))
+ if (!queue_add(ud, settings, 0))
ghb_value_free(settings);
// Validation of settings may have changed audio list
ghb_audio_list_refresh_all(ud);
}
+static gboolean
+title_multiple_can_select(GValue *settings_array, int index)
+{
+ gint count, ii;
+ GValue *settings, *gdest;
+ const char *dest;
+
+ settings = ghb_array_get_nth(settings_array, index);
+ gdest = ghb_settings_get_value(settings, "destination");
+ dest = g_value_get_string(gdest);
+ if (dest == NULL)
+ return FALSE;
+
+ count = ghb_array_len(settings_array);
+ count = count < index ? count : index;
+ for (ii = 0; ii < count; ii++)
+ {
+ const char *tmp;
+
+ settings = ghb_array_get_nth(settings_array, ii);
+ gdest = ghb_settings_get_value(settings, "destination");
+ tmp = g_value_get_string(gdest);
+ if (tmp != NULL && !strncmp(dest, tmp, PATH_MAX))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static GtkWidget *find_widget(GtkWidget *widget, gchar *name)
+{
+ const char *wname;
+ GtkWidget *result = NULL;
+
+ if (widget == NULL || name == NULL)
+ return NULL;
+
+ wname = gtk_widget_get_name(widget);
+ if (wname != NULL && !strncmp(wname, name, 80))
+ {
+ return widget;
+ }
+ if (GTK_IS_CONTAINER(widget))
+ {
+ GList *list, *link;
+ link = list = gtk_container_get_children(GTK_CONTAINER(widget));
+ while (link)
+ {
+ result = find_widget(GTK_WIDGET(link->data), name);
+ if (result != NULL)
+ break;
+ link = link->next;
+ }
+ g_list_free(list);
+ }
+ return result;
+}
+
+static void
+title_add_multiple_set_sensitive(GtkWidget *row, gboolean sensitive)
+{
+ GtkWidget *widget;
+ widget = find_widget(row, "title_selected");
+ gtk_widget_set_sensitive(widget, sensitive);
+ widget = find_widget(row, "title_label");
+ gtk_widget_set_sensitive(widget, sensitive);
+}
+
+static gboolean
+title_add_multiple_are_conflicts(signal_user_data_t *ud)
+{
+ gint count, ii;
+
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ if (!title_multiple_can_select(ud->settings_array, ii))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+title_add_multiple_set_conflict_label(
+ signal_user_data_t *ud,
+ gboolean are_conflicts)
+{
+ const gchar *msg;
+ static gboolean conflict_showing = FALSE;
+ GtkMessageType msg_type;
+
+ if (are_conflicts)
+ {
+ msg =
+ "<span foreground='red' weight='bold'>"
+ "Duplicate destination files detected.\n"
+ "Duplicates will not be added to the queue."
+ "</span>";
+ msg_type = GTK_MESSAGE_WARNING;
+ }
+ else
+ {
+ msg =
+ "Destination files OK. No duplicates detected.";
+ msg_type = GTK_MESSAGE_INFO;
+ }
+ if (are_conflicts ^ conflict_showing)
+ {
+ GtkInfoBar *info;
+ GtkContainer *content_area;
+ GList *list;
+ GtkLabel *label;
+
+ info = GTK_INFO_BAR(GHB_WIDGET(ud->builder,
+ "title_add_multiple_infobar"));
+ content_area = GTK_CONTAINER(gtk_info_bar_get_content_area(info));
+ list = gtk_container_get_children(content_area);
+ // Label is first in list
+ label = GTK_LABEL(list->data);
+ gtk_label_set_markup(label, msg);
+ gtk_info_bar_set_message_type(info, msg_type);
+ conflict_showing = are_conflicts;
+ }
+}
+
+static void
+title_add_multiple_check_conflicts(signal_user_data_t *ud)
+{
+ gint count, ii;
+ GValue *settings;
+ GtkWidget *row;
+ GtkListBox *list;
+ GtkToggleButton *selected;
+ gboolean can_select;
+ gboolean are_conflicts = FALSE;
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ selected = GTK_TOGGLE_BUTTON(find_widget(row, "title_selected"));
+
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ can_select = title_multiple_can_select(ud->settings_array, ii);
+ ghb_settings_set_boolean(settings, "title_selected", FALSE);
+ gtk_toggle_button_set_active(selected, FALSE);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+ are_conflicts |= !can_select;
+ }
+ title_add_multiple_set_conflict_label(ud, are_conflicts);
+}
+
+static gboolean clear_select_all_busy = FALSE;
+
+G_MODULE_EXPORT void
+title_add_multiple_select_all_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ gint count, ii;
+ GValue *settings;
+ GtkWidget *row;
+ GtkListBox *list;
+ GtkToggleButton *selected;
+ gboolean can_select;
+ GtkToggleButton *clear_all;
+ GtkToggleButton *select_all;
+
+ if (!ghb_widget_boolean(widget))
+ return;
+
+ clear_select_all_busy = TRUE;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(clear_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), TRUE);
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ selected = GTK_TOGGLE_BUTTON(find_widget(row, "title_selected"));
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ can_select = title_multiple_can_select(ud->settings_array, ii);
+ ghb_settings_set_boolean(settings, "title_selected", can_select);
+ gtk_toggle_button_set_active(selected, TRUE);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+ }
+ clear_select_all_busy = FALSE;
+}
+
+G_MODULE_EXPORT void
+title_add_multiple_clear_all_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ gint count, ii;
+ GValue *settings;
+ GtkWidget *row;
+ GtkListBox *list;
+ GtkToggleButton *selected;
+ GtkToggleButton *clear_all;
+ GtkToggleButton *select_all;
+
+ if (!ghb_widget_boolean(widget))
+ return;
+
+ clear_select_all_busy = TRUE;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(select_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), FALSE);
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ selected = GTK_TOGGLE_BUTTON(find_widget(row, "title_selected"));
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ ghb_settings_set_boolean(settings, "title_selected", FALSE);
+ gtk_toggle_button_set_active(selected, FALSE);
+ }
+ clear_select_all_busy = FALSE;
+}
+
+static void
+add_multiple_titles(signal_user_data_t *ud)
+{
+ gint count, ii;
+
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ GValue *settings;
+
+ settings = ghb_value_dup(ghb_array_get_nth(ud->settings_array, ii));
+ if (ghb_settings_get_boolean(settings, "title_selected"))
+ {
+ queue_add(ud, settings, ii);
+ }
+ }
+}
+
+static GtkListBoxRow*
+title_get_row(GtkWidget *widget)
+{
+ while (widget != NULL && G_OBJECT_TYPE(widget) != GTK_TYPE_LIST_BOX_ROW)
+ {
+ widget = gtk_widget_get_parent(widget);
+ }
+ return GTK_LIST_BOX_ROW(widget);
+}
+
+G_MODULE_EXPORT void
+title_selected_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ GValue *settings;
+ gboolean selected;
+ GtkToggleButton *select_all;
+ GtkToggleButton *clear_all;
+ gboolean can_select;
+
+ if (clear_select_all_busy)
+ return;
+
+ GtkListBoxRow * row = title_get_row(widget);
+ if (row == NULL)
+ return;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(select_all, FALSE);
+ gtk_toggle_button_set_active(clear_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), TRUE);
+
+ gint index = gtk_list_box_row_get_index(row);
+ selected = ghb_widget_boolean(widget);
+ settings = ghb_array_get_nth(ud->settings_array, index);
+ can_select = title_multiple_can_select(ud->settings_array, index);
+ ghb_settings_set_boolean(settings, "title_selected",
+ selected && can_select);
+}
+
G_MODULE_EXPORT void
-queue_add_all_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
+title_dest_file_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- g_debug("queue_add_all_clicked_cb ()");
- ghb_add_all_titles(ud);
+ GValue *settings;
+ gchar *dest_file, *dest_dir, *dest;
+ GtkListBoxRow * row = title_get_row(widget);
+ if (row == NULL)
+ return;
+ gint index = gtk_list_box_row_get_index(row);
+
+ dest_file = ghb_widget_string(widget);
+ settings = ghb_array_get_nth(ud->settings_array, index);
+
+ ghb_settings_set_string(settings, "dest_file", dest_file);
+ dest_dir = ghb_settings_get_string(settings, "dest_dir");
+ dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
+ ghb_settings_set_string(settings, "destination", dest);
+
+ // Check if changing the destination file name resolves
+ // a file name conflict. Enable selection if so.
+ // Disable selection if it creates a confict!!!
+ gboolean can_select;
+ can_select = title_multiple_can_select(ud->settings_array, index);
+ ghb_settings_set_boolean(settings, "title_selected", can_select);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+
+ g_free(dest_file);
+ g_free(dest_dir);
+ g_free(dest);
+
+ title_add_multiple_set_conflict_label(ud,
+ title_add_multiple_are_conflicts(ud));
+}
+
+G_MODULE_EXPORT void
+title_dest_dir_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ GValue *settings;
+ gchar *dest_file, *dest_dir, *dest;
+ GtkListBoxRow * row = title_get_row(widget);
+ if (row == NULL)
+ return;
+ gint index = gtk_list_box_row_get_index(row);
+
+ dest_dir = ghb_widget_string(widget);
+ settings = ghb_array_get_nth(ud->settings_array, index);
+
+ ghb_settings_set_string(settings, "dest_dir", dest_dir);
+ dest_file = ghb_settings_get_string(settings, "dest_file");
+ dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
+ ghb_settings_set_string(settings, "destination", dest);
+
+ // Check if changing the destination file name resolves
+ // a file name conflict. Enable selection if so.
+ // Disable selection if it creates a confict!!!
+ gboolean can_select;
+ can_select = title_multiple_can_select(ud->settings_array, index);
+ ghb_settings_set_boolean(settings, "title_selected", can_select);
+ title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select);
+
+ g_free(dest_file);
+ g_free(dest_dir);
+ g_free(dest);
+
+ title_add_multiple_set_conflict_label(ud,
+ title_add_multiple_are_conflicts(ud));
+}
+
+GtkWidget * title_create_row(signal_user_data_t *ud)
+{
+ GtkBox *hbox, *vbox_dest;
+ GtkCheckButton *selected;
+ GtkLabel *title;
+ GtkEntry *dest_file;
+ GtkFileChooserButton *dest_dir;
+
+ hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
+ gtk_box_set_spacing(hbox, 6);
+ gtk_widget_show(GTK_WIDGET(hbox));
+
+ // Select checkbox
+ selected = GTK_CHECK_BUTTON(gtk_check_button_new());
+ gtk_widget_set_tooltip_markup(GTK_WIDGET(selected),
+ "Select this title for adding to the queue.\n");
+ gtk_widget_set_valign(GTK_WIDGET(selected), GTK_ALIGN_CENTER);
+ gtk_widget_set_name(GTK_WIDGET(selected), "title_selected");
+ gtk_widget_show(GTK_WIDGET(selected));
+ g_signal_connect(selected, "toggled", (GCallback)title_selected_cb, ud);
+ gtk_box_pack_start(hbox, GTK_WIDGET(selected), FALSE, FALSE, 0);
+
+ // Title label
+ title = GTK_LABEL(gtk_label_new("No Title"));
+ gtk_label_set_width_chars(title, 12);
+ gtk_misc_set_alignment(GTK_MISC(title), 0, 0.5);
+ gtk_widget_set_name(GTK_WIDGET(title), "title_label");
+ gtk_widget_show(GTK_WIDGET(title));
+ gtk_box_pack_start(hbox, GTK_WIDGET(title), FALSE, FALSE, 0);
+
+ // Destination entry and file chooser
+ vbox_dest = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
+ //gtk_widget_set_hexpand(GTK_WIDGET(vbox_dest), TRUE);
+ dest_file = GTK_ENTRY(gtk_entry_new());
+ gtk_entry_set_width_chars(dest_file, 40);
+ gtk_widget_set_name(GTK_WIDGET(dest_file), "title_file");
+ //gtk_widget_set_hexpand(GTK_WIDGET(dest_file), TRUE);
+ gtk_widget_show(GTK_WIDGET(dest_file));
+ g_signal_connect(dest_file, "changed", (GCallback)title_dest_file_cb, ud);
+ gtk_box_pack_start(vbox_dest, GTK_WIDGET(dest_file), FALSE, FALSE, 0);
+ dest_dir = GTK_FILE_CHOOSER_BUTTON(
+ gtk_file_chooser_button_new("Destination Directory",
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER));
+ g_signal_connect(dest_dir, "selection-changed",
+ (GCallback)title_dest_dir_cb, ud);
+ gtk_widget_set_name(GTK_WIDGET(dest_dir), "title_dir");
+ gtk_widget_set_hexpand(GTK_WIDGET(dest_dir), TRUE);
+ gtk_widget_show(GTK_WIDGET(dest_dir));
+ gtk_box_pack_start(vbox_dest, GTK_WIDGET(dest_dir), FALSE, FALSE, 0);
+ gtk_widget_show(GTK_WIDGET(vbox_dest));
+ gtk_box_pack_start(hbox, GTK_WIDGET(vbox_dest), TRUE, TRUE, 0);
+
+ return GTK_WIDGET(hbox);
+}
+
+G_MODULE_EXPORT void
+queue_add_multiple_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ g_debug("queue_add_multiple_clicked_cb ()");
+
+ GtkListBox *list;
+ GtkWidget *row;
+ gint count, ii;
+ int max_title_len = 0;
+
+ list = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "title_add_multiple_list"));
+
+ // Set up the list of titles
+ count = ghb_array_len(ud->settings_array);
+ for (ii = 0; ii < count; ii++)
+ {
+ GValue *settings;
+ GtkLabel *label;
+ GtkEntry *entry;
+ GtkFileChooser *chooser;
+ gchar *title_label, *dest_dir, *dest_file;
+ int titleindex;
+ hb_title_t *title;
+
+ row = title_create_row(ud);
+ label = GTK_LABEL(find_widget(row, "title_label"));
+ entry = GTK_ENTRY(find_widget(row, "title_file"));
+ chooser = GTK_FILE_CHOOSER(find_widget(row, "title_dir"));
+
+ settings = ghb_array_get_nth(ud->settings_array, ii);
+ titleindex = ghb_settings_get_int(settings, "title_no");
+ title = ghb_get_title_info(titleindex);
+ if (title != NULL)
+ {
+ int len;
+
+ title_label = ghb_create_title_label(title);
+ len = strnlen(title_label, PATH_MAX);
+ if (len > max_title_len)
+ max_title_len = len;
+
+ dest_file = ghb_settings_get_string(settings, "dest_file");
+ dest_dir = ghb_settings_get_string(settings, "dest_dir");
+
+ gtk_label_set_markup(label, title_label);
+ gtk_entry_set_text(entry, dest_file);
+ gtk_file_chooser_set_filename(chooser, dest_dir);
+
+ g_free(title_label);
+ g_free(dest_file);
+ g_free(dest_dir);
+ }
+
+ gtk_list_box_insert(list, row, -1);
+ }
+ // Now we need to set the width of the title label since it
+ // can vary on each row
+ if (max_title_len > 60)
+ max_title_len = 60;
+ for (ii = 0; ii < count; ii++)
+ {
+ GtkWidget *row;
+ GtkLabel *label;
+
+ row = GTK_WIDGET(gtk_list_box_get_row_at_index(list, ii));
+ label = GTK_LABEL(find_widget(row, "title_label"));
+ gtk_label_set_max_width_chars(label, max_title_len);
+ gtk_label_set_width_chars(label, max_title_len);
+ gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
+ }
+
+ // Clear "select all" and "clear all" options
+ GtkToggleButton *select_all;
+ GtkToggleButton *clear_all;
+
+ clear_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_clear_all"));
+ select_all = GTK_TOGGLE_BUTTON(GHB_WIDGET(ud->builder,
+ "title_add_multiple_select_all"));
+ gtk_toggle_button_set_active(clear_all, FALSE);
+ gtk_toggle_button_set_active(select_all, FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(select_all), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_all), TRUE);
+
+ // Disable selection of files with duplicate file names.
+ title_add_multiple_check_conflicts(ud);
+
+ // Pop up the title multiple selections dialog
+ GtkResponseType response;
+ GtkWidget *dialog = GHB_WIDGET(ud->builder, "titla_add_multiple_dialog");
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(dialog);
+ if (response == GTK_RESPONSE_OK)
+ {
+ add_multiple_titles(ud);
+ }
+
+ // Clear title list
+ ghb_container_empty(GTK_CONTAINER(list));
}
G_MODULE_EXPORT void
@@ -1028,7 +1537,7 @@ ghb_queue_buttons_grey(signal_user_data_t *ud)
gtk_widget_set_sensitive(widget, show_start);
widget = GHB_WIDGET(ud->builder, "queue_add_menu");
gtk_widget_set_sensitive(widget, show_start);
- widget = GHB_WIDGET(ud->builder, "queue_add_all_menu");
+ widget = GHB_WIDGET(ud->builder, "queue_add_multiple_menu");
gtk_widget_set_sensitive(widget, show_start);
widget = GHB_WIDGET (ud->builder, "queue_start1");
@@ -1198,7 +1707,7 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
// The queue has no running or pending jobs.
// Add current settings to the queue, then run.
GValue *settings = ghb_value_dup(ud->settings);
- if (!ghb_queue_add(ud, settings, 0))
+ if (!queue_add(ud, settings, 0))
{
ghb_value_free(settings);
return;