diff options
author | John Stebbins <[email protected]> | 2019-06-26 13:39:29 -0700 |
---|---|---|
committer | John Stebbins <[email protected]> | 2019-06-26 13:39:29 -0700 |
commit | 42d54db85eb83c4273c1b2c07c2a342b5ba02115 (patch) | |
tree | 838fe6ba4df44144aaf7460675c9c5ac0a2b7331 /gtk/src/queuehandler.c | |
parent | 5c87d987aaaaf79e02f9e1dfe58f72b2afed0a58 (diff) |
LinGui: implement queue reordering
Add drag & drop queue reordering to new queue design
Diffstat (limited to 'gtk/src/queuehandler.c')
-rw-r--r-- | gtk/src/queuehandler.c | 1860 |
1 files changed, 1020 insertions, 840 deletions
diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index 496bcfd92..bf723a1d3 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -39,8 +39,40 @@ #include "queuehandler.h" void ghb_queue_buttons_grey(signal_user_data_t *ud); + +// Callbacks G_MODULE_EXPORT void queue_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud); +G_MODULE_EXPORT void +queue_drag_begin_cb(GtkWidget * widget, GdkDragContext * context, + signal_user_data_t * ud); +G_MODULE_EXPORT void +queue_drag_end_cb(GtkWidget * widget, GdkDragContext * context, + signal_user_data_t * ud); +G_MODULE_EXPORT void +queue_drag_data_get_cb(GtkWidget * widget, GdkDragContext * context, + GtkSelectionData * selection_data, + guint info, guint time, signal_user_data_t * ud); +G_MODULE_EXPORT void +title_selected_cb(GtkWidget *widget, signal_user_data_t *ud); +G_MODULE_EXPORT void +title_dest_file_cb(GtkWidget *widget, signal_user_data_t *ud); +G_MODULE_EXPORT void +title_dest_dir_cb(GtkWidget *widget, signal_user_data_t *ud); + +static GtkTargetEntry queue_drag_entries[] = { + { "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 } +}; + +void +ghb_queue_drag_n_drop_init(signal_user_data_t * ud) +{ + GtkWidget * widget; + + widget = GHB_WIDGET(ud->builder, "queue_list"); + gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_MOTION|GTK_DEST_DEFAULT_DROP, + queue_drag_entries, 1, GDK_ACTION_MOVE); +} static GtkWidget *find_widget(GtkWidget *widget, gchar *name) { @@ -71,12 +103,6 @@ static GtkWidget *find_widget(GtkWidget *widget, gchar *name) return result; } -void -ghb_queue_drag_n_drop_init(signal_user_data_t * ud) -{ - -} - static void queue_update_summary(GhbValue * queueDict, signal_user_data_t *ud) { @@ -842,27 +868,6 @@ ghb_queue_selection_init(signal_user_data_t * ud) } } -G_MODULE_EXPORT void -queue_list_selection_changed_cb(GtkListBox *box, GtkListBoxRow *row, - signal_user_data_t *ud) -{ - GhbValue * queueDict = NULL; - int index = -1; - - if (row != NULL) - { - index = gtk_list_box_row_get_index(row); - } - if (index >= 0 && index < ghb_array_len(ud->queue)) - { - queueDict = ghb_array_get(ud->queue, index); - } - queue_update_summary(queueDict, ud); - queue_update_stats(queueDict, ud); - ghb_queue_select_log(ud); - ghb_queue_buttons_grey(ud); -} - char * ghb_subtitle_short_description(const GhbValue *subsource, const GhbValue *subsettings) @@ -918,71 +923,6 @@ ghb_subtitle_short_description(const GhbValue *subsource, return desc; } -static void -add_to_queue_list(signal_user_data_t *ud, GhbValue *queueDict) -{ - GtkListBox * lb; - GtkBox * hbox, * vbox; - GtkWidget * status_icon; - GtkWidget * dest_label; - GtkWidget * delete_button; - GtkWidget * progress; - GhbValue * uiDict; - const char * dest; - gchar * basename; - - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - - vbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 6)); - gtk_widget_set_margin_start(GTK_WIDGET(vbox), 12); - hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6)); - - status_icon = gtk_image_new_from_icon_name("hb-source", - GTK_ICON_SIZE_BUTTON); - - gtk_widget_set_name(status_icon, "queue_item_status"); - gtk_image_set_pixel_size(GTK_IMAGE(status_icon), 16); - gtk_widget_set_hexpand(status_icon, FALSE); - - dest = ghb_dict_get_string(uiDict, "destination"); - basename = g_path_get_basename(dest); - dest_label = gtk_label_new(basename); - g_free(basename); - gtk_widget_set_name(dest_label, "queue_item_dest"); - gtk_widget_set_hexpand(dest_label, TRUE); - gtk_widget_set_halign(dest_label, GTK_ALIGN_FILL); - gtk_label_set_justify(GTK_LABEL(dest_label), GTK_JUSTIFY_LEFT); - gtk_label_set_xalign(GTK_LABEL(dest_label), 0.0); - gtk_label_set_width_chars(GTK_LABEL(dest_label), 50); - gtk_label_set_ellipsize(GTK_LABEL(dest_label), PANGO_ELLIPSIZE_END); - - delete_button = gtk_button_new_from_icon_name("hb-remove", - GTK_ICON_SIZE_BUTTON); - gtk_button_set_relief(GTK_BUTTON(delete_button), GTK_RELIEF_NONE); - g_signal_connect(delete_button, "clicked", - (GCallback)queue_remove_clicked_cb, ud); - gtk_widget_set_hexpand(delete_button, FALSE); - - progress = gtk_progress_bar_new(); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.0); - gtk_widget_set_name(progress, "queue_item_progress"); - - ghb_box_pack_start(hbox, GTK_WIDGET(status_icon)); - ghb_box_pack_start(hbox, GTK_WIDGET(dest_label)); - ghb_box_pack_start(hbox, GTK_WIDGET(delete_button)); - - ghb_box_pack_start(vbox, GTK_WIDGET(hbox)); - ghb_box_pack_start(vbox, GTK_WIDGET(progress)); - - gtk_widget_show(GTK_WIDGET(vbox)); - gtk_widget_show(GTK_WIDGET(hbox)); - gtk_widget_show(status_icon); - gtk_widget_show(dest_label); - gtk_widget_show(delete_button); - gtk_list_box_insert(lb, GTK_WIDGET(vbox), -1); -} - void ghb_queue_progress_set_visible(signal_user_data_t *ud, int index, gboolean visible) @@ -1407,6 +1347,92 @@ save_queue_file(signal_user_data_t *ud) } static void +add_to_queue_list(signal_user_data_t *ud, GhbValue *queueDict) +{ + GtkListBox * lb; + GtkWidget * row; + GtkBox * hbox, * vbox, * dbox; + GtkWidget * ebox; + GtkWidget * status_icon; + GtkWidget * dest_label; + GtkWidget * delete_button; + GtkWidget * progress; + GhbValue * uiDict; + const char * dest; + gchar * basename; + + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + + row = gtk_list_box_row_new(); + vbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 6)); + gtk_widget_set_margin_start(GTK_WIDGET(vbox), 12); + hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6)); + dbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6)); + ebox = gtk_event_box_new(); + + status_icon = gtk_image_new_from_icon_name("hb-source", + GTK_ICON_SIZE_BUTTON); + + gtk_widget_set_name(status_icon, "queue_item_status"); + gtk_image_set_pixel_size(GTK_IMAGE(status_icon), 16); + gtk_widget_set_hexpand(status_icon, FALSE); + + dest = ghb_dict_get_string(uiDict, "destination"); + basename = g_path_get_basename(dest); + dest_label = gtk_label_new(basename); + g_free(basename); + gtk_widget_set_name(dest_label, "queue_item_dest"); + gtk_widget_set_hexpand(dest_label, TRUE); + gtk_widget_set_halign(dest_label, GTK_ALIGN_FILL); + gtk_label_set_justify(GTK_LABEL(dest_label), GTK_JUSTIFY_LEFT); + gtk_label_set_xalign(GTK_LABEL(dest_label), 0.0); + gtk_label_set_width_chars(GTK_LABEL(dest_label), 50); + gtk_label_set_ellipsize(GTK_LABEL(dest_label), PANGO_ELLIPSIZE_END); + + delete_button = gtk_button_new_from_icon_name("hb-remove", + GTK_ICON_SIZE_BUTTON); + gtk_button_set_relief(GTK_BUTTON(delete_button), GTK_RELIEF_NONE); + g_signal_connect(delete_button, "clicked", + (GCallback)queue_remove_clicked_cb, ud); + gtk_widget_set_hexpand(delete_button, FALSE); + + progress = gtk_progress_bar_new(); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.0); + gtk_widget_set_name(progress, "queue_item_progress"); + + ghb_box_pack_start(dbox, GTK_WIDGET(status_icon)); + ghb_box_pack_start(dbox, GTK_WIDGET(dest_label)); + gtk_container_add(GTK_CONTAINER(ebox), GTK_WIDGET(dbox)); + ghb_box_pack_start(hbox, GTK_WIDGET(ebox)); + ghb_box_pack_start(hbox, GTK_WIDGET(delete_button)); + + ghb_box_pack_start(vbox, GTK_WIDGET(hbox)); + ghb_box_pack_start(vbox, GTK_WIDGET(progress)); + gtk_container_add(GTK_CONTAINER(row), GTK_WIDGET(vbox)); + + gtk_widget_show(GTK_WIDGET(row)); + gtk_widget_show(GTK_WIDGET(vbox)); + gtk_widget_show(GTK_WIDGET(hbox)); + gtk_widget_show(GTK_WIDGET(dbox)); + gtk_widget_show(GTK_WIDGET(ebox)); + gtk_widget_show(status_icon); + gtk_widget_show(dest_label); + gtk_widget_show(delete_button); + gtk_list_box_insert(lb, row, -1); + + // style class for CSS settings + gtk_style_context_add_class(gtk_widget_get_style_context(row), "row"); + // set row as a source for drag & drop + gtk_drag_source_set(ebox, GDK_BUTTON1_MASK, queue_drag_entries, 1, + GDK_ACTION_MOVE); + g_signal_connect(ebox, "drag-begin", G_CALLBACK(queue_drag_begin_cb), NULL); + g_signal_connect(ebox, "drag-end", G_CALLBACK(queue_drag_end_cb), NULL); + g_signal_connect(ebox, "drag-data-get", + G_CALLBACK(queue_drag_data_get_cb), NULL); +} + +static void open_queue_file(signal_user_data_t *ud) { GtkWidget *dialog; @@ -1440,7 +1466,7 @@ open_queue_file(signal_user_data_t *ud) } GhbValue *queue; - char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog)); + char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); gtk_widget_destroy(dialog); queue = ghb_read_settings_file(filename); @@ -1470,157 +1496,6 @@ open_queue_file(signal_user_data_t *ud) g_free (filename); } -G_MODULE_EXPORT void -show_queue_action_cb(GSimpleAction *action, GVariant *value, - signal_user_data_t *ud) -{ - GtkWidget * queue_window; - gboolean state = g_variant_get_boolean(value); - - g_simple_action_set_state(action, value); - queue_window = GHB_WIDGET(ud->builder, "queue_window"); - gtk_widget_set_visible(queue_window, state); -} - -G_MODULE_EXPORT gboolean -queue_window_delete_cb(GtkWidget *xwidget, GdkEvent *event, signal_user_data_t *ud) -{ - gtk_widget_set_visible(xwidget, FALSE); - GtkWidget *widget = GHB_WIDGET (ud->builder, "show_queue"); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), FALSE); - return TRUE; -} - -GhbValue *ghb_queue_edit_settings = NULL; - -G_MODULE_EXPORT void -queue_edit_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - GtkListBox * lb; - GtkListBoxRow * row; - gint index, status; - GhbValue * queueDict, *uiDict; - - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - row = gtk_list_box_get_selected_row(lb); - if (row != NULL) - { - index = gtk_list_box_row_get_index(row); - if (index < 0 || index >= ghb_array_len(ud->queue)) - return; - - queueDict = ghb_array_get(ud->queue, index); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - ghb_queue_edit_settings = ghb_value_dup(uiDict); - ghb_dict_set(ghb_queue_edit_settings, - "Job", ghb_value_dup(ghb_dict_get(queueDict, "Job"))); - status = ghb_dict_get_int(uiDict, "job_status"); - if (status == GHB_QUEUE_PENDING) - { - // Remove the selected item - gtk_container_remove(GTK_CONTAINER(lb), GTK_WIDGET(row)); - // Remove the corresponding item from the queue list - ghb_array_remove(ud->queue, index); - ghb_update_pending(ud); - } - const gchar *source; - source = ghb_dict_get_string(ghb_queue_edit_settings, "source"); - ghb_do_scan(ud, source, 0, FALSE); - - GtkWidget *widget = GHB_WIDGET(ud->builder, "show_queue"); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), FALSE); - } -} - -G_MODULE_EXPORT void -queue_export_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - save_queue_file(ud); -} - -G_MODULE_EXPORT void -queue_import_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - open_queue_file(ud); -} - -G_MODULE_EXPORT void -queue_open_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) -{ - open_queue_file(ud); -} - -G_MODULE_EXPORT void -queue_open_source_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - GtkListBox * lb; - GtkListBoxRow * row; - gint index; - GhbValue * queueDict, * titleDict; - GString * str; - const char * path; - char * dir, * uri; - - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - row = gtk_list_box_get_selected_row(lb); - if (row != NULL) - { - index = gtk_list_box_row_get_index(row); - if (index < 0 || index >= ghb_array_len(ud->queue)) - { - return; - } - queueDict = ghb_array_get(ud->queue, index); - titleDict = ghb_dict_get(queueDict, "Title"); - path = ghb_dict_get_string(titleDict, "Path"); - dir = g_path_get_dirname(path); - str = g_string_new(NULL); - g_string_printf(str, "file://%s", dir); - uri = g_string_free(str, FALSE); - ghb_browse_uri(ud, uri); - g_free(uri); - g_free(dir); - } -} - -G_MODULE_EXPORT void -queue_open_dest_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - GtkListBox * lb; - GtkListBoxRow * row; - gint index; - GhbValue * queueDict, * uiDict; - GString * str; - const char * path; - char * dir, * uri; - - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - row = gtk_list_box_get_selected_row(lb); - if (row != NULL) - { - index = gtk_list_box_row_get_index(row); - if (index < 0 || index >= ghb_array_len(ud->queue)) - { - return; - } - queueDict = ghb_array_get(ud->queue, index); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - path = ghb_dict_get_string(uiDict, "destination"); - dir = g_path_get_dirname(path); - str = g_string_new(NULL); - g_string_printf(str, "file://%s", dir); - uri = g_string_free(str, FALSE); - ghb_browse_uri(ud, uri); - g_free(uri); - g_free(dir); - } -} - gint64 ghb_dest_free_space(GhbValue *settings) { @@ -1964,16 +1839,6 @@ queue_add(signal_user_data_t *ud, GhbValue *settings, gint batch) return TRUE; } -G_MODULE_EXPORT void -queue_add_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - queue_add(ud, ud->settings, 0); - ghb_queue_selection_init(ud); - // Validation of settings may have changed audio list - ghb_audio_list_refresh_all(ud); -} - static gboolean title_multiple_can_select(GhbValue *settings_array, int index) { @@ -2122,85 +1987,6 @@ title_add_multiple_check_conflicts(signal_user_data_t *ud) 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; - GhbValue *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(ud->settings_array, ii); - can_select = title_multiple_can_select(ud->settings_array, ii); - ghb_dict_set_bool(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; - GhbValue *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(ud->settings_array, ii); - ghb_dict_set_bool(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) { @@ -2230,119 +2016,6 @@ list_box_get_row(GtkWidget *widget) return GTK_LIST_BOX_ROW(widget); } -G_MODULE_EXPORT void -title_selected_cb(GtkWidget *widget, signal_user_data_t *ud) -{ - GhbValue *settings; - gboolean selected; - GtkToggleButton *select_all; - GtkToggleButton *clear_all; - gboolean can_select; - - if (clear_select_all_busy) - return; - - GtkListBoxRow * row = list_box_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(ud->settings_array, index); - can_select = title_multiple_can_select(ud->settings_array, index); - ghb_dict_set_bool(settings, "title_selected", - selected && can_select); -} - -G_MODULE_EXPORT void -title_dest_file_cb(GtkWidget *widget, signal_user_data_t *ud) -{ - GhbValue *settings; - const gchar *dest_dir; - gchar *dest_file, *dest; - GtkListBoxRow * row = list_box_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(ud->settings_array, index); - - ghb_dict_set_string(settings, "dest_file", dest_file); - dest_dir = ghb_dict_get_string(settings, "dest_dir"); - dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file); - ghb_dict_set_string(settings, "destination", dest); - GhbValue *dest_dict = ghb_get_job_dest_settings(settings); - ghb_dict_set_string(dest_dict, "File", dest); - - // Check if changing the destination file name resolves - // a file name conflict. Enable selection if so. - // Disable selection if it creates a conflict!!! - gboolean selected, can_select; - - widget = find_widget(GTK_WIDGET(row), "title_selected"); - selected = ghb_widget_boolean(widget); - can_select = title_multiple_can_select(ud->settings_array, index); - - ghb_dict_set_bool(settings, "title_selected", selected && can_select); - title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select); - - g_free(dest_file); - 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) -{ - GhbValue *settings; - const gchar *dest_file; - gchar *dest_dir, *dest; - GtkListBoxRow * row = list_box_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(ud->settings_array, index); - - ghb_dict_set_string(settings, "dest_dir", dest_dir); - dest_file = ghb_dict_get_string(settings, "dest_file"); - dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file); - ghb_dict_set_string(settings, "destination", dest); - GhbValue *dest_dict = ghb_get_job_dest_settings(settings); - ghb_dict_set_string(dest_dict, "File", dest); - - // Check if changing the destination file name resolves - // a file name conflict. Enable selection if so. - // Disable selection if it creates a conflict!!! - gboolean selected, can_select; - - widget = find_widget(GTK_WIDGET(row), "title_selected"); - selected = ghb_widget_boolean(widget); - can_select = title_multiple_can_select(ud->settings_array, index); - - ghb_dict_set_bool(settings, "title_selected", selected && can_select); - title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select); - - 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; @@ -2408,6 +2081,467 @@ GtkWidget * title_create_row(signal_user_data_t *ud) return GTK_WIDGET(hbox); } +static void +ghb_queue_remove_row_internal(signal_user_data_t *ud, int index) +{ + GtkListBox * lb; + GtkListBoxRow * row; + GhbValue * queueDict, * uiDict; + + if (index < 0 || index >= ghb_array_len(ud->queue)) + { + return; + } + + queueDict = ghb_array_get(ud->queue, index); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + int status = ghb_dict_get_int(uiDict, "job_status"); + if (status == GHB_QUEUE_RUNNING) + { + // Ask if wants to stop encode. + if (!ghb_cancel_encode2(ud, NULL)) + { + return; + } + int unique_id = ghb_dict_get_int(uiDict, "job_unique_id"); + ghb_remove_job(unique_id); + } + ghb_array_remove(ud->queue, index); + + // Update UI + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + row = gtk_list_box_get_row_at_index(lb, index); + gtk_container_remove(GTK_CONTAINER(lb), GTK_WIDGET(row)); +} + +void +ghb_queue_remove_row(signal_user_data_t *ud, int index) +{ + ghb_queue_remove_row_internal(ud, index); + ghb_save_queue(ud->queue); + ghb_queue_buttons_grey(ud); +} + +void +ghb_queue_buttons_grey(signal_user_data_t *ud) +{ + GtkWidget * widget; + GSimpleAction * action; + gint queue_count; + gint title_id, titleindex; + const hb_title_t * title; + gint queue_state, scan_state; + gboolean allow_start, show_stop, allow_add, paused; + GtkListBox * lb; + GtkListBoxRow * row; + + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + row = gtk_list_box_get_selected_row(lb); + + queue_count = ghb_array_len(ud->queue); + title_id = ghb_dict_get_int(ud->settings, "title"); + title = ghb_lookup_title(title_id, &titleindex); + + queue_state = ghb_get_queue_state(); + scan_state = ghb_get_scan_state(); + + show_stop = queue_state & + (GHB_STATE_WORKING | GHB_STATE_SEARCHING | + GHB_STATE_SCANNING | GHB_STATE_MUXING | GHB_STATE_PAUSED); + allow_start = !(scan_state & GHB_STATE_SCANNING) && + (title != NULL || queue_count > 0); + allow_add = !(scan_state & GHB_STATE_SCANNING) && title != NULL; + + + paused = queue_state & GHB_STATE_PAUSED; + + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-export")); + g_simple_action_set_enabled(action, !!queue_count); + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-add")); + g_simple_action_set_enabled(action, allow_add); + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-add-all")); + g_simple_action_set_enabled(action, allow_add); + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-start")); + g_simple_action_set_enabled(action, allow_start || show_stop); + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-pause")); + g_simple_action_set_enabled(action, show_stop); + + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-reset")); + g_simple_action_set_enabled(action, row != NULL); + + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-edit")); + g_simple_action_set_enabled(action, row != NULL); + + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-open-source")); + g_simple_action_set_enabled(action, row != NULL); + + action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), + "queue-open-dest")); + g_simple_action_set_enabled(action, row != NULL); + + widget = GHB_WIDGET (ud->builder, "queue_start"); + if (show_stop) + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Encoding")); + } + else + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Start")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Start Encoding")); + } + widget = GHB_WIDGET (ud->builder, "queue_list_start"); + if (show_stop) + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Encoding")); + } + else + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Start")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Start Encoding")); + } + widget = GHB_WIDGET (ud->builder, "queue_start_menu"); + if (show_stop) + { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("S_top Encoding")); + gtk_widget_set_tooltip_text(widget, _("Stop Encoding")); + } + else + { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("_Start Encoding")); + gtk_widget_set_tooltip_text(widget, _("Start Encoding")); + } + + widget = GHB_WIDGET (ud->builder, "queue_pause"); + if (paused) + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Resume")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Resume Encoding")); + } + else + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-pause"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Pause")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Pause Encoding")); + } + widget = GHB_WIDGET (ud->builder, "queue_list_pause"); + if (paused) + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Resume")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Resume Encoding")); + } + else + { + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-pause"); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Pause")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Pause Encoding")); + } + widget = GHB_WIDGET (ud->builder, "queue_pause_menu"); + if (paused) + { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("_Resume Encoding")); + gtk_widget_set_tooltip_text(widget, _("Resume Encoding")); + } + else + { + gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("_Pause Encoding")); + gtk_widget_set_tooltip_text(widget, _("Pause Encoding")); + } +} + +gboolean +ghb_reload_queue(signal_user_data_t *ud) +{ + GhbValue *queue; + gint count, ii; + gint pid; + gint status; + GhbValue *queueDict, *uiDict; + + g_debug("ghb_reload_queue"); + +find_pid: + pid = ghb_find_pid_file(); + if (pid < 0) + goto done; + + queue = ghb_load_old_queue(pid); + ghb_remove_old_queue_file(pid); + + // Look for unfinished entries + count = ghb_array_len(queue); + for (ii = count-1; ii >= 0; ii--) + { + queueDict = ghb_array_get(queue, ii); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + if (uiDict == NULL || + ghb_dict_get_value(uiDict, "job_status") == NULL) + { + ghb_array_remove(queue, ii); + continue; + } + status = ghb_dict_get_int(uiDict, "job_status"); + if (status == GHB_QUEUE_DONE || status == GHB_QUEUE_CANCELED) + { + ghb_array_remove(queue, ii); + continue; + } + } + count = ghb_array_len(queue); + if (count == 0) + { + ghb_value_free(&queue); + goto find_pid; + } + else + { + GtkWidget *widget = GHB_WIDGET(ud->builder, "show_queue"); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), TRUE); + ud->queue = queue; + for (ii = 0; ii < count; ii++) + { + queueDict = ghb_array_get(queue, ii); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + ghb_dict_set_int(uiDict, "job_unique_id", 0); + ghb_dict_set_int(uiDict, "job_status", GHB_QUEUE_PENDING); + add_to_queue_list(ud, queueDict); + } + ghb_queue_buttons_grey(ud); + ghb_save_queue(ud->queue); + ghb_update_pending(ud); + ghb_queue_selection_init(ud); + } + +done: + ghb_write_pid_file(); + + return FALSE; +} + +G_MODULE_EXPORT gboolean +queue_key_press_cb( + GtkWidget * widget, + GdkEvent * event, + signal_user_data_t * ud) +{ + GtkListBox * lb; + GtkListBoxRow * row; + gint index; + guint keyval; + + ghb_event_get_keyval(event, &keyval); + if (keyval != GDK_KEY_Delete) + return FALSE; + + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + row = gtk_list_box_get_selected_row(lb); + if (row != NULL) + { + index = gtk_list_box_row_get_index(row); + ghb_queue_remove_row_internal(ud, index); + ghb_save_queue(ud->queue); + return TRUE; + } + return FALSE; +} + +G_MODULE_EXPORT void +show_queue_action_cb(GSimpleAction *action, GVariant *value, + signal_user_data_t *ud) +{ + GtkWidget * queue_window; + gboolean state = g_variant_get_boolean(value); + + g_simple_action_set_state(action, value); + queue_window = GHB_WIDGET(ud->builder, "queue_window"); + gtk_widget_set_visible(queue_window, state); +} + +G_MODULE_EXPORT gboolean +queue_window_delete_cb(GtkWidget *xwidget, GdkEvent *event, signal_user_data_t *ud) +{ + gtk_widget_set_visible(xwidget, FALSE); + GtkWidget *widget = GHB_WIDGET (ud->builder, "show_queue"); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), FALSE); + return TRUE; +} + +GhbValue *ghb_queue_edit_settings = NULL; + +G_MODULE_EXPORT void +queue_edit_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) +{ + GtkListBox * lb; + GtkListBoxRow * row; + gint index, status; + GhbValue * queueDict, *uiDict; + + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + row = gtk_list_box_get_selected_row(lb); + if (row != NULL) + { + index = gtk_list_box_row_get_index(row); + if (index < 0 || index >= ghb_array_len(ud->queue)) + return; + + queueDict = ghb_array_get(ud->queue, index); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + ghb_queue_edit_settings = ghb_value_dup(uiDict); + ghb_dict_set(ghb_queue_edit_settings, + "Job", ghb_value_dup(ghb_dict_get(queueDict, "Job"))); + status = ghb_dict_get_int(uiDict, "job_status"); + if (status == GHB_QUEUE_PENDING) + { + // Remove the selected item + gtk_container_remove(GTK_CONTAINER(lb), GTK_WIDGET(row)); + // Remove the corresponding item from the queue list + ghb_array_remove(ud->queue, index); + ghb_update_pending(ud); + } + const gchar *source; + source = ghb_dict_get_string(ghb_queue_edit_settings, "source"); + ghb_do_scan(ud, source, 0, FALSE); + + GtkWidget *widget = GHB_WIDGET(ud->builder, "show_queue"); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), FALSE); + } +} + +G_MODULE_EXPORT void +queue_export_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) +{ + save_queue_file(ud); +} + +G_MODULE_EXPORT void +queue_import_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) +{ + open_queue_file(ud); +} + +G_MODULE_EXPORT void +queue_open_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + open_queue_file(ud); +} + +G_MODULE_EXPORT void +queue_open_source_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) +{ + GtkListBox * lb; + GtkListBoxRow * row; + gint index; + GhbValue * queueDict, * titleDict; + GString * str; + const char * path; + char * dir, * uri; + + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + row = gtk_list_box_get_selected_row(lb); + if (row != NULL) + { + index = gtk_list_box_row_get_index(row); + if (index < 0 || index >= ghb_array_len(ud->queue)) + { + return; + } + queueDict = ghb_array_get(ud->queue, index); + titleDict = ghb_dict_get(queueDict, "Title"); + path = ghb_dict_get_string(titleDict, "Path"); + dir = g_path_get_dirname(path); + str = g_string_new(NULL); + g_string_printf(str, "file://%s", dir); + uri = g_string_free(str, FALSE); + ghb_browse_uri(ud, uri); + g_free(uri); + g_free(dir); + } +} + +G_MODULE_EXPORT void +queue_open_dest_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) +{ + GtkListBox * lb; + GtkListBoxRow * row; + gint index; + GhbValue * queueDict, * uiDict; + GString * str; + const char * path; + char * dir, * uri; + + lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); + row = gtk_list_box_get_selected_row(lb); + if (row != NULL) + { + index = gtk_list_box_row_get_index(row); + if (index < 0 || index >= ghb_array_len(ud->queue)) + { + return; + } + queueDict = ghb_array_get(ud->queue, index); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + path = ghb_dict_get_string(uiDict, "destination"); + dir = g_path_get_dirname(path); + str = g_string_new(NULL); + g_string_printf(str, "file://%s", dir); + uri = g_string_free(str, FALSE); + ghb_browse_uri(ud, uri); + g_free(uri); + g_free(dir); + } +} + +G_MODULE_EXPORT void +queue_list_selection_changed_cb(GtkListBox *box, GtkListBoxRow *row, + signal_user_data_t *ud) +{ + GhbValue * queueDict = NULL; + int index = -1; + + if (row != NULL) + { + index = gtk_list_box_row_get_index(row); + } + if (index >= 0 && index < ghb_array_len(ud->queue)) + { + queueDict = ghb_array_get(ud->queue, index); + } + queue_update_summary(queueDict, ud); + queue_update_stats(queueDict, ud); + ghb_queue_select_log(ud); + ghb_queue_buttons_grey(ud); +} + +G_MODULE_EXPORT void +queue_add_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) +{ + queue_add(ud, ud->settings, 0); + ghb_queue_selection_init(ud); + // Validation of settings may have changed audio list + ghb_audio_list_refresh_all(ud); +} + G_MODULE_EXPORT void queue_add_all_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud) @@ -2518,47 +2652,6 @@ queue_add_all_action_cb(GSimpleAction *action, GVariant *param, ghb_container_empty(GTK_CONTAINER(list)); } -static void -ghb_queue_remove_row_internal(signal_user_data_t *ud, int index) -{ - GtkListBox * lb; - GtkListBoxRow * row; - GhbValue * queueDict, * uiDict; - - if (index < 0 || index >= ghb_array_len(ud->queue)) - { - return; - } - - queueDict = ghb_array_get(ud->queue, index); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - int status = ghb_dict_get_int(uiDict, "job_status"); - if (status == GHB_QUEUE_RUNNING) - { - // Ask if wants to stop encode. - if (!ghb_cancel_encode2(ud, NULL)) - { - return; - } - int unique_id = ghb_dict_get_int(uiDict, "job_unique_id"); - ghb_remove_job(unique_id); - } - ghb_array_remove(ud->queue, index); - - // Update UI - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - row = gtk_list_box_get_row_at_index(lb, index); - gtk_container_remove(GTK_CONTAINER(lb), GTK_WIDGET(row)); -} - -void -ghb_queue_remove_row(signal_user_data_t *ud, int index) -{ - ghb_queue_remove_row_internal(ud, index); - ghb_save_queue(ud->queue); - ghb_queue_buttons_grey(ud); -} - G_MODULE_EXPORT void queue_delete_all_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud) @@ -2669,454 +2762,541 @@ queue_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_queue_buttons_grey(ud); } -static gint -find_last_finished(GhbValue *queue) +G_MODULE_EXPORT void +queue_start_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) { GhbValue *queueDict, *uiDict; - gint ii, count; + gboolean running = FALSE; + gint count, ii; gint status; + gint state; - g_debug("find_last_finished"); - count = ghb_array_len(queue); + state = ghb_get_queue_state(); + if (state & (GHB_STATE_WORKING | GHB_STATE_SEARCHING | + GHB_STATE_SCANNING | GHB_STATE_MUXING)) + { + ghb_cancel_encode(ud, _("You are currently encoding. " + "What would you like to do?\n\n")); + return; + } + + count = ghb_array_len(ud->queue); for (ii = 0; ii < count; ii++) { - queueDict = ghb_array_get(queue, ii); + queueDict = ghb_array_get(ud->queue, ii); uiDict = ghb_dict_get(queueDict, "uiSettings"); status = ghb_dict_get_int(uiDict, "job_status"); - if (status != GHB_QUEUE_DONE && status != GHB_QUEUE_RUNNING) + if ((status == GHB_QUEUE_RUNNING) || + (status == GHB_QUEUE_PENDING)) { - return ii-1; + running = TRUE; + break; } } - return -1; + if (!running) + { + // The queue has no running or pending jobs. + // Add current settings to the queue, then run. + if (!queue_add(ud, ud->settings, 0)) + { + return; + } + ghb_queue_selection_init(ud); + // Validation of settings may have changed audio list + ghb_audio_list_refresh_all(ud); + } + if (state == GHB_STATE_IDLE) + { + // Add the first pending queue item and start + ghb_start_next_job(ud); + } } -// This little bit is needed to prevent the default drag motion -// handler from expanding rows if you hover over them while -// dragging. -// Also controls where valid drop locations are -G_MODULE_EXPORT gboolean -queue_drag_motion_cb( - GtkListBox * lb, - GdkDragContext * ctx, - gint x, - gint y, - guint time, - signal_user_data_t * ud) +G_MODULE_EXPORT void +queue_pause_action_cb(GSimpleAction *action, GVariant *param, + signal_user_data_t *ud) { - gint src_index, dst_index, status, finished, height; - GhbValue * queueDict, * uiDict; - GtkListBox * src_lb; - GtkListBoxRow * src_row, * dst_row; + ghb_pause_resume_queue(); +} - height = gtk_widget_get_allocated_height(GTK_WIDGET(lb)); - if (y <= 6 || y >= height - 6) - { - return FALSE; - } +static gboolean clear_select_all_busy = FALSE; - src_lb = GTK_LIST_BOX(gtk_drag_get_source_widget(ctx)); - if (src_lb == NULL || src_lb != lb) - { - return TRUE; - } +G_MODULE_EXPORT void +title_add_multiple_select_all_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + gint count, ii; + GhbValue *settings; + GtkWidget *row; + GtkListBox *list; + GtkToggleButton *selected; + gboolean can_select; + GtkToggleButton *clear_all; + GtkToggleButton *select_all; - // This bit checks to see if the source is allowed to be - // moved. Only pending and canceled items may be moved. - src_row = gtk_list_box_get_selected_row(src_lb); - if (src_row == NULL) - { - gdk_drag_status(ctx, GDK_ACTION_MOVE, time); - return TRUE; - } - src_index = gtk_list_box_row_get_index(src_row); - queueDict = ghb_array_get(ud->queue, src_index); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - status = ghb_dict_get_int(uiDict, "job_status"); - if (status != GHB_QUEUE_PENDING && status != GHB_QUEUE_CANCELED) - { - gdk_drag_status(ctx, 0, time); - return TRUE; - } + if (!ghb_widget_boolean(widget)) + return; - // The rest checks that the destination is a valid position - // in the list. Can not move above any finished or running items - dst_row = gtk_list_box_get_row_at_y(lb, y); - if (dst_row == NULL) - { - gdk_drag_status(ctx, GDK_ACTION_MOVE, time); - return TRUE; - } - dst_index = gtk_list_box_row_get_index(dst_row); + clear_select_all_busy = TRUE; - finished = find_last_finished(ud->queue); - if (dst_index < finished) + 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++) { - gdk_drag_status(ctx, 0, time); - return TRUE; + 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(ud->settings_array, ii); + can_select = title_multiple_can_select(ud->settings_array, ii); + ghb_dict_set_bool(settings, "title_selected", can_select); + gtk_toggle_button_set_active(selected, TRUE); + title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select); } - gtk_list_box_drag_highlight_row(lb, dst_row); - gdk_drag_status(ctx, GDK_ACTION_MOVE, time); - return TRUE; + clear_select_all_busy = FALSE; } G_MODULE_EXPORT void -queue_drop_cb( - GtkListBox * lb, - GdkDragContext * ctx, - gint x, - gint y, - GtkSelectionData * selection_data, - guint info, - guint t, - signal_user_data_t * ud) +title_add_multiple_clear_all_cb(GtkWidget *widget, signal_user_data_t *ud) { - GtkListBox * src_lb; - GtkListBoxRow * src_row, * dst_row; - gint src_index, dst_index; - GhbValue * queueDict, * uiDict; + gint count, ii; + GhbValue *settings; + GtkWidget *row; + GtkListBox *list; + GtkToggleButton *selected; + GtkToggleButton *clear_all; + GtkToggleButton *select_all; - dst_row = gtk_list_box_get_row_at_y(lb, y); - if (dst_row == NULL) - { - // Dropping after last item - dst_index = ghb_array_len(ud->queue); - } - else + 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++) { - dst_index = gtk_list_box_row_get_index(dst_row); + 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(ud->settings_array, ii); + ghb_dict_set_bool(settings, "title_selected", FALSE); + gtk_toggle_button_set_active(selected, FALSE); } + clear_select_all_busy = FALSE; +} - src_lb = GTK_LIST_BOX(gtk_drag_get_source_widget(ctx)); - if (src_lb == NULL || src_lb != lb) - { +G_MODULE_EXPORT void +title_selected_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GhbValue *settings; + gboolean selected; + GtkToggleButton *select_all; + GtkToggleButton *clear_all; + gboolean can_select; + + if (clear_select_all_busy) return; - } - src_row = gtk_list_box_get_selected_row(src_lb); - if (src_row == NULL) - { + GtkListBoxRow * row = list_box_get_row(widget); + if (row == NULL) return; - } - src_index = gtk_list_box_row_get_index(src_row); - if (src_index < dst_index) - { - // The source row is removed before re-inserting it elsewhere - // in the list. If the source is before the dest, the dest position - // moves - dst_index -= 1; - } - g_object_ref(src_row); - gtk_container_remove(GTK_CONTAINER(lb), GTK_WIDGET(src_row)); - gtk_list_box_insert(lb, GTK_WIDGET(src_row), dst_index); - g_object_unref(src_row); - queueDict = ghb_array_get(ud->queue, src_index); - uiDict = ghb_dict_get(queueDict, "uiSettings"); + 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); - ghb_value_incref(queueDict); - ghb_array_remove(ud->queue, src_index); - ghb_array_insert(ud->queue, dst_index, queueDict); + gint index = gtk_list_box_row_get_index(row); + selected = ghb_widget_boolean(widget); + settings = ghb_array_get(ud->settings_array, index); + can_select = title_multiple_can_select(ud->settings_array, index); + ghb_dict_set_bool(settings, "title_selected", + selected && can_select); +} - // Reset job to pending - ghb_dict_set_int(uiDict, "job_status", GHB_QUEUE_PENDING); +G_MODULE_EXPORT void +title_dest_file_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GhbValue *settings; + const gchar *dest_dir; + gchar *dest_file, *dest; + GtkListBoxRow * row = list_box_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(ud->settings_array, index); + + ghb_dict_set_string(settings, "dest_file", dest_file); + dest_dir = ghb_dict_get_string(settings, "dest_dir"); + dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file); + ghb_dict_set_string(settings, "destination", dest); + GhbValue *dest_dict = ghb_get_job_dest_settings(settings); + ghb_dict_set_string(dest_dict, "File", dest); + + // Check if changing the destination file name resolves + // a file name conflict. Enable selection if so. + // Disable selection if it creates a conflict!!! + gboolean selected, can_select; + + widget = find_widget(GTK_WIDGET(row), "title_selected"); + selected = ghb_widget_boolean(widget); + can_select = title_multiple_can_select(ud->settings_array, index); - // TODO: update job status icon in dst + ghb_dict_set_bool(settings, "title_selected", selected && can_select); + title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select); + + g_free(dest_file); + g_free(dest); + + title_add_multiple_set_conflict_label(ud, + title_add_multiple_are_conflicts(ud)); } -void -ghb_queue_buttons_grey(signal_user_data_t *ud) +G_MODULE_EXPORT void +title_dest_dir_cb(GtkWidget *widget, signal_user_data_t *ud) { - GtkWidget * widget; - GSimpleAction * action; - gint queue_count; - gint title_id, titleindex; - const hb_title_t * title; - gint queue_state, scan_state; - gboolean allow_start, show_stop, allow_add, paused; - GtkListBox * lb; - GtkListBoxRow * row; + GhbValue *settings; + const gchar *dest_file; + gchar *dest_dir, *dest; + GtkListBoxRow * row = list_box_get_row(widget); + if (row == NULL) + return; + gint index = gtk_list_box_row_get_index(row); - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - row = gtk_list_box_get_selected_row(lb); + dest_dir = ghb_widget_string(widget); + settings = ghb_array_get(ud->settings_array, index); - queue_count = ghb_array_len(ud->queue); - title_id = ghb_dict_get_int(ud->settings, "title"); - title = ghb_lookup_title(title_id, &titleindex); + ghb_dict_set_string(settings, "dest_dir", dest_dir); + dest_file = ghb_dict_get_string(settings, "dest_file"); + dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file); + ghb_dict_set_string(settings, "destination", dest); + GhbValue *dest_dict = ghb_get_job_dest_settings(settings); + ghb_dict_set_string(dest_dict, "File", dest); - queue_state = ghb_get_queue_state(); - scan_state = ghb_get_scan_state(); + // Check if changing the destination file name resolves + // a file name conflict. Enable selection if so. + // Disable selection if it creates a conflict!!! + gboolean selected, can_select; - show_stop = queue_state & - (GHB_STATE_WORKING | GHB_STATE_SEARCHING | - GHB_STATE_SCANNING | GHB_STATE_MUXING | GHB_STATE_PAUSED); - allow_start = !(scan_state & GHB_STATE_SCANNING) && - (title != NULL || queue_count > 0); - allow_add = !(scan_state & GHB_STATE_SCANNING) && title != NULL; + widget = find_widget(GTK_WIDGET(row), "title_selected"); + selected = ghb_widget_boolean(widget); + can_select = title_multiple_can_select(ud->settings_array, index); + ghb_dict_set_bool(settings, "title_selected", selected && can_select); + title_add_multiple_set_sensitive(GTK_WIDGET(row), can_select); - paused = queue_state & GHB_STATE_PAUSED; + g_free(dest_dir); + g_free(dest); - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-export")); - g_simple_action_set_enabled(action, !!queue_count); - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-add")); - g_simple_action_set_enabled(action, allow_add); - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-add-all")); - g_simple_action_set_enabled(action, allow_add); - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-start")); - g_simple_action_set_enabled(action, allow_start || show_stop); - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-pause")); - g_simple_action_set_enabled(action, show_stop); + title_add_multiple_set_conflict_label(ud, + title_add_multiple_are_conflicts(ud)); +} - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-reset")); - g_simple_action_set_enabled(action, row != NULL); +// Set up view of row to be dragged +G_MODULE_EXPORT void +queue_drag_begin_cb(GtkWidget * widget, + GdkDragContext * context, + signal_user_data_t * ud) +{ + GtkListBox * lb; + GtkWidget * row; + GtkAllocation alloc; + cairo_surface_t * surface; + cairo_t * cr; + int x, y; + + row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW); + lb = GTK_LIST_BOX(gtk_widget_get_parent(row)); + gtk_list_box_select_row(lb, GTK_LIST_BOX_ROW(row)); + gtk_widget_get_allocation(row, &alloc); + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + alloc.width, alloc.height); + cr = cairo_create(surface); + + gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-icon"); + gtk_widget_draw(row, cr); + gtk_style_context_remove_class(gtk_widget_get_style_context(row), + "drag-icon"); + + gtk_widget_translate_coordinates(widget, row, 0, 0, &x, &y); + cairo_surface_set_device_offset(surface, -x, -y); + gtk_drag_set_icon_surface(context, surface); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + + g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row); + gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row"); +} - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-edit")); - g_simple_action_set_enabled(action, row != NULL); +G_MODULE_EXPORT void +queue_drag_end_cb(GtkWidget * widget, + GdkDragContext * context, + signal_user_data_t * ud) +{ + GtkWidget * row; + + row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW); + g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", NULL); + gtk_style_context_remove_class(gtk_widget_get_style_context(row), + "drag-row"); + gtk_style_context_remove_class(gtk_widget_get_style_context(row), + "drag-hover"); +} - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-open-source")); - g_simple_action_set_enabled(action, row != NULL); +// Set selection to the row being dragged +G_MODULE_EXPORT void +queue_drag_data_get_cb(GtkWidget * widget, + GdkDragContext * context, + GtkSelectionData * selection_data, + guint info, + guint time, + signal_user_data_t * ud) +{ + GtkWidget * row; - action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(ud->app), - "queue-open-dest")); - g_simple_action_set_enabled(action, row != NULL); + row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW); + gtk_selection_data_set(selection_data, + gdk_atom_intern_static_string("GTK_LIST_BOX_ROW"), 32, + (const guchar *)&row, sizeof (gpointer)); +} - widget = GHB_WIDGET (ud->builder, "queue_start"); - if (show_stop) - { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Encoding")); - } - else - { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Start")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Start Encoding")); - } - widget = GHB_WIDGET (ud->builder, "queue_list_start"); - if (show_stop) - { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Encoding")); - } - else - { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Start")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Start Encoding")); - } - widget = GHB_WIDGET (ud->builder, "queue_start_menu"); - if (show_stop) +G_MODULE_EXPORT void +queue_drag_leave_cb( + GtkListBox * lb, + GdkDragContext * ctx, + guint time, + signal_user_data_t * ud) +{ + GtkWidget * drag_row; + GtkWidget * row_before; + GtkWidget * row_after; + + drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "drag-row")); + row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "row-before")); + row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "row-after")); + + gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), + "drag-hover"); + if (row_before) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("S_top Encoding")); - gtk_widget_set_tooltip_text(widget, _("Stop Encoding")); + gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), + "drag-hover-bottom"); } - else + if (row_after) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("_Start Encoding")); - gtk_widget_set_tooltip_text(widget, _("Start Encoding")); + gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), + "drag-hover-top"); } +} - widget = GHB_WIDGET (ud->builder, "queue_pause"); - if (paused) - { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Resume")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Resume Encoding")); - } - else +static GtkListBoxRow * +get_last_row(GtkListBox * list) +{ + int i; + GtkListBoxRow * row; + + row = NULL; + for (i = 0; ; i++) { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-pause"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Pause")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Pause Encoding")); + GtkListBoxRow * tmp; + tmp = gtk_list_box_get_row_at_index(list, i); + if (tmp == NULL) + return row; + row = tmp; } - widget = GHB_WIDGET (ud->builder, "queue_list_pause"); - if (paused) + return row; +} + +static GtkListBoxRow * +get_row_before (GtkListBox * list, GtkListBoxRow * row) +{ + int pos = gtk_list_box_row_get_index(row); + return gtk_list_box_get_row_at_index(list, pos - 1); +} + +static GtkListBoxRow * +get_row_after (GtkListBox * list, GtkListBoxRow * row) +{ + int pos = gtk_list_box_row_get_index(row); + return gtk_list_box_get_row_at_index(list, pos + 1); +} + +G_MODULE_EXPORT gboolean +queue_drag_motion_cb( + GtkListBox * lb, + GdkDragContext * ctx, + gint x, + gint y, + guint time, + signal_user_data_t * ud) +{ + GtkAllocation alloc; + GtkWidget * row; + int hover_row_y; + int hover_row_height; + GtkWidget * drag_row; + GtkWidget * row_before; + GtkWidget * row_after; + + row = GTK_WIDGET(gtk_list_box_get_row_at_y(GTK_LIST_BOX(lb), y)); + + drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "drag-row")); + row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "row-before")); + row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "row-after")); + + gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), + "drag-hover"); + if (row_before) { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-start"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Resume")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Resume Encoding")); + gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), + "drag-hover-bottom"); } - else + if (row_after) { - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-pause"); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Pause")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Pause Encoding")); + gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), + "drag-hover-top"); } - widget = GHB_WIDGET (ud->builder, "queue_pause_menu"); - if (paused) + + if (row) { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("_Resume Encoding")); - gtk_widget_set_tooltip_text(widget, _("Resume Encoding")); + gtk_widget_get_allocation(row, &alloc); + hover_row_y = alloc.y; + hover_row_height = alloc.height; + + if (y < hover_row_y + hover_row_height/2) + { + row_after = row; + row_before = GTK_WIDGET(get_row_before(lb, GTK_LIST_BOX_ROW(row))); + } + else + { + row_before = row; + row_after = GTK_WIDGET(get_row_after(lb, GTK_LIST_BOX_ROW(row))); + } } else { - gtk_menu_item_set_label(GTK_MENU_ITEM(widget), _("_Pause Encoding")); - gtk_widget_set_tooltip_text(widget, _("Pause Encoding")); + row_before = GTK_WIDGET(get_last_row(lb)); + row_after = NULL; } -} -G_MODULE_EXPORT void -queue_start_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) -{ - GhbValue *queueDict, *uiDict; - gboolean running = FALSE; - gint count, ii; - gint status; - gint state; + g_object_set_data(G_OBJECT(lb), "row-before", row_before); + g_object_set_data(G_OBJECT(lb), "row-after", row_after); - state = ghb_get_queue_state(); - if (state & (GHB_STATE_WORKING | GHB_STATE_SEARCHING | - GHB_STATE_SCANNING | GHB_STATE_MUXING)) + if (drag_row == row_before || drag_row == row_after) { - ghb_cancel_encode(ud, _("You are currently encoding. " - "What would you like to do?\n\n")); - return; + gtk_style_context_add_class(gtk_widget_get_style_context(drag_row), + "drag-hover"); + return FALSE; } - count = ghb_array_len(ud->queue); - for (ii = 0; ii < count; ii++) + if (row_before) { - queueDict = ghb_array_get(ud->queue, ii); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - status = ghb_dict_get_int(uiDict, "job_status"); - if ((status == GHB_QUEUE_RUNNING) || - (status == GHB_QUEUE_PENDING)) - { - running = TRUE; - break; - } - } - if (!running) - { - // The queue has no running or pending jobs. - // Add current settings to the queue, then run. - if (!queue_add(ud, ud->settings, 0)) - { - return; - } - ghb_queue_selection_init(ud); - // Validation of settings may have changed audio list - ghb_audio_list_refresh_all(ud); + gtk_style_context_add_class(gtk_widget_get_style_context(row_before), + "drag-hover-bottom"); } - if (state == GHB_STATE_IDLE) + if (row_after) { - // Add the first pending queue item and start - ghb_start_next_job(ud); + gtk_style_context_add_class(gtk_widget_get_style_context(row_after), "drag-hover-top"); } + + return TRUE; } G_MODULE_EXPORT void -queue_pause_action_cb(GSimpleAction *action, GVariant *param, - signal_user_data_t *ud) +queue_drag_data_received_cb(GtkListBox * lb, + GdkDragContext * context, + gint x, + gint y, + GtkSelectionData * selection_data, + guint info, + guint32 time, + signal_user_data_t * ud) { - ghb_pause_resume_queue(); -} + GtkWidget * row_before; + GtkWidget * row_after; + GtkWidget * src_row; + int src_index, dst_index; -gboolean -ghb_reload_queue(signal_user_data_t *ud) -{ - GhbValue *queue; - gint count, ii; - gint pid; - gint status; - GhbValue *queueDict, *uiDict; + row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "row-before")); + row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(lb), "row-after")); - g_debug("ghb_reload_queue"); + g_object_set_data(G_OBJECT(lb), "row-before", NULL); + g_object_set_data(G_OBJECT(lb), "row-after", NULL); -find_pid: - pid = ghb_find_pid_file(); - if (pid < 0) - goto done; + if (row_before) + { + gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), + "drag-hover-bottom"); + } + if (row_after) + { + gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), + "drag-hover-top"); + } - queue = ghb_load_old_queue(pid); - ghb_remove_old_queue_file(pid); + src_row = GTK_WIDGET(*(gpointer*)gtk_selection_data_get_data(selection_data)); - // Look for unfinished entries - count = ghb_array_len(queue); - for (ii = count-1; ii >= 0; ii--) + if (src_row == row_after) { - queueDict = ghb_array_get(queue, ii); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - if (uiDict == NULL || - ghb_dict_get_value(uiDict, "job_status") == NULL) - { - ghb_array_remove(queue, ii); - continue; - } - status = ghb_dict_get_int(uiDict, "job_status"); - if (status == GHB_QUEUE_DONE || status == GHB_QUEUE_CANCELED) - { - ghb_array_remove(queue, ii); - continue; - } + gtk_list_box_select_row(lb, GTK_LIST_BOX_ROW(src_row)); + return; } - count = ghb_array_len(queue); - if (count == 0) + + src_index = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(src_row)); + if (row_after) { - ghb_value_free(&queue); - goto find_pid; + dst_index = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_after)); } else { - GtkWidget *widget = GHB_WIDGET(ud->builder, "show_queue"); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), TRUE); - ud->queue = queue; - for (ii = 0; ii < count; ii++) - { - queueDict = ghb_array_get(queue, ii); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - ghb_dict_set_int(uiDict, "job_unique_id", 0); - ghb_dict_set_int(uiDict, "job_status", GHB_QUEUE_PENDING); - add_to_queue_list(ud, queueDict); - } - ghb_queue_buttons_grey(ud); - ghb_save_queue(ud->queue); - ghb_update_pending(ud); - ghb_queue_selection_init(ud); + dst_index = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_before)) + 1; } -done: - ghb_write_pid_file(); + if (src_index < dst_index) + { + // The source row is removed before re-inserting it elsewhere + // in the list. If the source is before the dest, the dest position + // moves + dst_index -= 1; + } + g_object_ref(src_row); - return FALSE; -} + gtk_container_remove(GTK_CONTAINER(lb), src_row); + gtk_list_box_insert(lb, src_row, dst_index); + g_object_unref(src_row); -G_MODULE_EXPORT gboolean -queue_key_press_cb( - GtkWidget * widget, - GdkEvent * event, - signal_user_data_t * ud) -{ - GtkListBox * lb; - GtkListBoxRow * row; - gint index; - guint keyval; + GhbValue * queueDict; - ghb_event_get_keyval(event, &keyval); - if (keyval != GDK_KEY_Delete) - return FALSE; + queueDict = ghb_array_get(ud->queue, src_index); + ghb_value_incref(queueDict); + ghb_array_remove(ud->queue, src_index); + ghb_array_insert(ud->queue, dst_index, queueDict); - lb = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "queue_list")); - row = gtk_list_box_get_selected_row(lb); - if (row != NULL) - { - index = gtk_list_box_row_get_index(row); - ghb_queue_remove_row_internal(ud, index); - ghb_save_queue(ud->queue); - return TRUE; - } - return FALSE; -} + // Force refresh of current selection + gtk_list_box_unselect_row(lb, GTK_LIST_BOX_ROW(src_row)); + gtk_list_box_select_row(lb, GTK_LIST_BOX_ROW(src_row)); + ghb_save_queue(ud->queue); +} |