summaryrefslogtreecommitdiffstats
path: root/gtk/src/callbacks.c
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2008-09-13 20:04:28 +0000
committerjstebbins <[email protected]>2008-09-13 20:04:28 +0000
commit91ca41626288377d6a7c24bc76677e8f90378460 (patch)
treefab0e4f122b3fd80a580bdb685e8e060a3640153 /gtk/src/callbacks.c
parent3feae357a5d62add8c0bc32753b2b679bdb8aa9a (diff)
LinGui: Add queue drag n drop reordering
Also add option to add chapter numbers to auto-generated destination name git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1693 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'gtk/src/callbacks.c')
-rw-r--r--gtk/src/callbacks.c335
1 files changed, 296 insertions, 39 deletions
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c
index 238f36f67..05a7cba73 100644
--- a/gtk/src/callbacks.c
+++ b/gtk/src/callbacks.c
@@ -41,6 +41,7 @@ static GList* dvd_device_list();
static gboolean cancel_encode();
static void audio_list_refresh_selected(signal_user_data_t *ud);
static GValue* get_selected_asettings(signal_user_data_t *ud);
+static gint find_last_finished(GValue *queue);
// This is a dependency map used for greying widgets
// that are dependent on the state of another widget.
@@ -260,16 +261,16 @@ on_quit1_activate(GtkMenuItem *quit, signal_user_data_t *ud)
{
gint state = ghb_get_queue_state();
g_debug("on_quit1_activate ()");
- if (state & GHB_STATE_WORKING)
- {
- if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
- {
+ if (state & GHB_STATE_WORKING)
+ {
+ if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
+ {
ghb_hb_cleanup(FALSE);
- gtk_main_quit();
- return;
- }
- return;
- }
+ gtk_main_quit();
+ return;
+ }
+ return;
+ }
ghb_hb_cleanup(FALSE);
gtk_main_quit();
}
@@ -287,7 +288,27 @@ set_destination(signal_user_data_t *ud)
extension = ghb_settings_get_string(ud->settings, "container");
dir = g_path_get_dirname (filename);
vol_name = ghb_settings_get_string(ud->settings, "volume_label");
- new_name = g_strdup_printf("%s/%s.%s", dir, vol_name, extension);
+ if (ghb_settings_get_boolean(ud->settings, "chapters_in_destination"))
+ {
+ gint start, end;
+
+ start = ghb_settings_get_int(ud->settings, "start_chapter");
+ end = ghb_settings_get_int(ud->settings, "end_chapter");
+ if (start == end)
+ {
+ new_name = g_strdup_printf("%s/%s-%d.%s",
+ dir, vol_name, start, extension);
+ }
+ else
+ {
+ new_name = g_strdup_printf("%s/%s-%d-%d.%s",
+ dir, vol_name, start, end, extension);
+ }
+ }
+ else
+ {
+ new_name = g_strdup_printf("%s/%s.%s", dir, vol_name, extension);
+ }
ghb_ui_update(ud, "destination", ghb_string_value(new_name));
g_free(filename);
g_free(extension);
@@ -743,11 +764,11 @@ destination_browse_clicked_cb(GtkButton *button, signal_user_data_t *ud)
g_debug("destination_browse_clicked_cb ()");
destname = ghb_settings_get_string(ud->settings, "destination");
dialog = gtk_file_chooser_dialog_new ("Choose Destination",
- NULL,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), destname);
basename = g_path_get_basename(destname);
g_free(destname);
@@ -778,7 +799,7 @@ window_destroy_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *
g_debug("window_destroy_event_cb ()");
ghb_hb_cleanup(FALSE);
gtk_main_quit();
- return FALSE;
+ return FALSE;
}
gboolean
@@ -786,19 +807,19 @@ window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *u
{
gint state = ghb_get_queue_state();
g_debug("window_delete_event_cb ()");
- if (state & GHB_STATE_WORKING)
- {
- if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
- {
+ if (state & GHB_STATE_WORKING)
+ {
+ if (cancel_encode("Closing HandBrake will terminate encoding.\n"))
+ {
ghb_hb_cleanup(FALSE);
- gtk_main_quit();
- return FALSE;
- }
- return TRUE;
- }
+ gtk_main_quit();
+ return FALSE;
+ }
+ return TRUE;
+ }
ghb_hb_cleanup(FALSE);
gtk_main_quit();
- return FALSE;
+ return FALSE;
}
static void
@@ -1292,7 +1313,7 @@ validate_filter_widget(signal_user_data_t *ud, const gchar *name)
gboolean
deint_tweak_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
- signal_user_data_t *ud)
+ signal_user_data_t *ud)
{
g_debug("deint_tweak_focus_out_cb ()");
validate_filter_widget(ud, "tweak_deinterlace");
@@ -1301,7 +1322,7 @@ deint_tweak_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
gboolean
denoise_tweak_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
- signal_user_data_t *ud)
+ signal_user_data_t *ud)
{
g_debug("denoise_tweak_focus_out_cb ()");
validate_filter_widget(ud, "tweak_noise");
@@ -1385,6 +1406,10 @@ start_chapter_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
start = ghb_settings_get_int(ud->settings, "start_chapter");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(end_ch), start, end);
check_dependency(ud, widget);
+ if (ghb_settings_get_boolean(ud->settings, "chapters_in_destination"))
+ {
+ set_destination(ud);
+ }
}
void
@@ -1399,6 +1424,10 @@ end_chapter_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
end = ghb_settings_get_int(ud->settings, "end_chapter");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(start_ch), start, end);
check_dependency(ud, widget);
+ if (ghb_settings_get_boolean(ud->settings, "chapters_in_destination"))
+ {
+ set_destination(ud);
+ }
}
void
@@ -1513,7 +1542,7 @@ generic_entry_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
gboolean
generic_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
- signal_user_data_t *ud)
+ signal_user_data_t *ud)
{
g_debug("generic_focus_out_cb ()");
ghb_widget_to_setting(ud->settings, widget);
@@ -1567,7 +1596,7 @@ x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
gboolean
x264_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
- signal_user_data_t *ud)
+ signal_user_data_t *ud)
{
gchar *options, *sopts;
@@ -1689,7 +1718,7 @@ audio_list_refresh_selected(signal_user_data_t *ud)
gchar *track, *codec, *br, *sr, *mix, *drc;
gchar *s_track, *s_codec, *s_br, *s_sr, *s_mix;
gdouble s_drc;
- // Get the row number
+ // Get the row number
treepath = gtk_tree_model_get_path (store, &iter);
indices = gtk_tree_path_get_indices (treepath);
row = indices[0];
@@ -1763,7 +1792,7 @@ get_selected_asettings(signal_user_data_t *ud)
selection = gtk_tree_view_get_selection (treeview);
if (gtk_tree_selection_get_selected(selection, &store, &iter))
{
- // Get the row number
+ // Get the row number
treepath = gtk_tree_model_get_path (store, &iter);
indices = gtk_tree_path_get_indices (treepath);
row = indices[0];
@@ -1888,7 +1917,7 @@ audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
{
gtk_tree_selection_select_iter (selection, &nextIter);
}
- // Get the row number
+ // Get the row number
treepath = gtk_tree_model_get_path (store, &iter);
indices = gtk_tree_path_get_indices (treepath);
row = indices[0];
@@ -1902,6 +1931,8 @@ audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
audio_list = ghb_settings_get_value(ud->settings, "audio_list");
if (row >= ghb_array_len(audio_list))
return;
+ GValue *old = ghb_array_get_nth(audio_list, row);
+ ghb_value_free(old);
ghb_array_remove(audio_list, row);
}
}
@@ -2329,13 +2360,14 @@ queue_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t
}
static void
-add_to_queue_list(signal_user_data_t *ud, GValue *settings)
+add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter)
{
GtkTreeView *treeview;
GtkTreeIter iter;
GtkTreeStore *store;
gchar *info;
gint num_pass = 1;
+ gint status;
gint ii;
GtkTreeIter citer;
gchar *vcodec, *container, *acodec, *dest, *preset, *vol_name;
@@ -2360,8 +2392,31 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings)
pass2 ? 2:1, pass2 ? "Passes":"Pass"
);
- gtk_tree_store_append(store, &iter, NULL);
- gtk_tree_store_set(store, &iter, 0, "hb-queue-job", 1, info, 2, "hb-queue-delete", -1);
+ if (piter)
+ iter = *piter;
+ else
+ gtk_tree_store_append(store, &iter, NULL);
+
+ gtk_tree_store_set(store, &iter, 1, info, 2, "hb-queue-delete", -1);
+ status = ghb_settings_get_int(settings, "job_status");
+ switch (status)
+ {
+ case GHB_QUEUE_PENDING:
+ gtk_tree_store_set(store, &iter, 0, "hb-queue-job", -1);
+ break;
+ case GHB_QUEUE_CANCELED:
+ gtk_tree_store_set(store, &iter, 0, "hb-canceled", -1);
+ break;
+ case GHB_QUEUE_RUNNING:
+ gtk_tree_store_set(store, &iter, 0, "hb-working0", -1);
+ break;
+ case GHB_QUEUE_DONE:
+ gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
+ break;
+ default:
+ gtk_tree_store_set(store, &iter, 0, "hb-queue-job", -1);
+ break;
+ }
g_free(info);
vcodec = ghb_settings_get_combo_option(settings, "video_codec");
@@ -2722,7 +2777,7 @@ queue_add(signal_user_data_t *ud)
titlenum = ghb_get_title_number(titleindex);
ghb_settings_set_int(settings, "titlenum", titlenum);
ghb_array_append(ud->queue, settings);
- add_to_queue_list(ud, settings);
+ add_to_queue_list(ud, settings, NULL);
ghb_save_queue(ud->queue);
return TRUE;
@@ -2800,7 +2855,10 @@ queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
// Remove the selected item
gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
// Remove the corresponding item from the queue list
+ GValue *old = ghb_array_get_nth(ud->queue, row);
+ ghb_value_free(old);
ghb_array_remove(ud->queue, row);
+ ghb_save_queue(ud->queue);
}
else
{
@@ -2808,6 +2866,202 @@ queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *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
+gboolean
+queue_drag_motion_cb(
+ GtkTreeView *tv,
+ GdkDragContext *ctx,
+ gint x,
+ gint y,
+ guint time,
+ signal_user_data_t *ud)
+{
+ GtkTreePath *path = NULL;
+ GtkTreeViewDropPosition pos;
+ gint *indices, row, status, finished;
+ GValue *js;
+ GtkTreeIter iter;
+ GtkTreeView *srctv;
+ GtkTreeModel *model;
+ GtkTreeSelection *select;
+
+ // This bit checks to see if the source is allowed to be
+ // moved. Only pending and canceled items may be moved.
+ srctv = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx));
+ select = gtk_tree_view_get_selection (srctv);
+ gtk_tree_selection_get_selected (select, &model, &iter);
+ path = gtk_tree_model_get_path (model, &iter);
+ indices = gtk_tree_path_get_indices(path);
+ row = indices[0];
+ gtk_tree_path_free(path);
+ js = ghb_array_get_nth(ud->queue, row);
+ status = ghb_settings_get_int(js, "job_status");
+ if (status != GHB_QUEUE_PENDING && status != GHB_QUEUE_CANCELED)
+ {
+ gdk_drag_status(ctx, 0, time);
+ return TRUE;
+ }
+
+ // The reset checks that the destination is a valid position
+ // in the list. Can not move above any finished or running items
+ gtk_tree_view_get_dest_row_at_pos (tv, x, y, &path, &pos);
+ if (path == NULL)
+ {
+ gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
+ return TRUE;
+ }
+ indices = gtk_tree_path_get_indices(path);
+ row = indices[0];
+ js = ghb_array_get_nth(ud->queue, row);
+
+ finished = find_last_finished(ud->queue);
+ if (row < finished)
+ {
+ gtk_tree_path_free(path);
+ gdk_drag_status(ctx, 0, time);
+ return TRUE;
+ }
+ if (pos != GTK_TREE_VIEW_DROP_AFTER &&
+ row == finished)
+ {
+ gtk_tree_path_free(path);
+ gdk_drag_status(ctx, 0, time);
+ return TRUE;
+ }
+ gtk_tree_view_set_drag_dest_row(tv, path, pos);
+ gtk_tree_path_free(path);
+ gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
+ return TRUE;
+}
+
+void
+queue_drag_cb(
+ GtkTreeView *dstwidget,
+ GdkDragContext *dc,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info, guint t,
+ signal_user_data_t *ud)
+{
+ GtkTreePath *path = NULL;
+ //GtkTreeModel *model;
+ GtkTreeViewDropPosition pos;
+ GtkTreeIter dstiter, srciter;
+ gint *indices, row;
+ GValue *js;
+
+ GtkTreeModel *dstmodel = gtk_tree_view_get_model(dstwidget);
+
+ g_debug("queue_drag_cb ()");
+ // This doesn't work here for some reason...
+ // gtk_tree_view_get_drag_dest_row(dstwidget, &path, &pos);
+ gtk_tree_view_get_dest_row_at_pos (dstwidget, x, y, &path, &pos);
+ // This little hack is needed because attempting to drop after
+ // the last item gives us no path or pos.
+ if (path == NULL)
+ {
+ gint n_children;
+
+ n_children = gtk_tree_model_iter_n_children(dstmodel, NULL);
+ if (n_children)
+ {
+ pos = GTK_TREE_VIEW_DROP_AFTER;
+ path = gtk_tree_path_new_from_indices(n_children-1, -1);
+ }
+ else
+ {
+ pos = GTK_TREE_VIEW_DROP_BEFORE;
+ path = gtk_tree_path_new_from_indices(0, -1);
+ }
+ }
+ if (path)
+ {
+ if (gtk_tree_path_get_depth(path) > 1)
+ gtk_tree_path_up(path);
+ if (gtk_tree_model_get_iter (dstmodel, &dstiter, path))
+ {
+ GtkTreeIter iter;
+ GtkTreeView *srcwidget;
+ GtkTreeModel *srcmodel;
+ GtkTreeSelection *select;
+ GtkTreePath *srcpath = NULL;
+ GtkTreePath *dstpath = NULL;
+
+ srcwidget = GTK_TREE_VIEW(gtk_drag_get_source_widget(dc));
+ //srcmodel = gtk_tree_view_get_model(srcwidget);
+ select = gtk_tree_view_get_selection (srcwidget);
+ gtk_tree_selection_get_selected (select, &srcmodel, &srciter);
+
+ srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
+ indices = gtk_tree_path_get_indices(srcpath);
+ row = indices[0];
+ gtk_tree_path_free(srcpath);
+ js = ghb_array_get_nth(ud->queue, row);
+
+ switch (pos)
+ {
+ case GTK_TREE_VIEW_DROP_BEFORE:
+ case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+ gtk_tree_store_insert_before (GTK_TREE_STORE (dstmodel),
+ &iter, NULL, &dstiter);
+ break;
+
+ case GTK_TREE_VIEW_DROP_AFTER:
+ case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+ gtk_tree_store_insert_after (GTK_TREE_STORE (dstmodel),
+ &iter, NULL, &dstiter);
+ break;
+
+ default:
+ break;
+ }
+ // Reset job to pending
+ ghb_settings_set_int(js, "job_status", GHB_QUEUE_PENDING);
+ add_to_queue_list(ud, js, &iter);
+
+ dstpath = gtk_tree_model_get_path (dstmodel, &iter);
+ indices = gtk_tree_path_get_indices(dstpath);
+ row = indices[0];
+ gtk_tree_path_free(dstpath);
+ ghb_array_insert(ud->queue, row, js);
+
+ srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
+ indices = gtk_tree_path_get_indices(srcpath);
+ row = indices[0];
+ gtk_tree_path_free(srcpath);
+ ghb_array_remove(ud->queue, row);
+ gtk_tree_store_remove (GTK_TREE_STORE (srcmodel), &srciter);
+ ghb_save_queue(ud->queue);
+ }
+ gtk_tree_path_free(path);
+ }
+}
+
+
+static gint
+find_last_finished(GValue *queue)
+{
+ GValue *js;
+ gint ii, count;
+ gint status;
+
+ g_debug("find_last_finished");
+ count = ghb_array_len(queue);
+ for (ii = 0; ii < count; ii++)
+ {
+ js = ghb_array_get_nth(queue, ii);
+ status = ghb_settings_get_int(js, "job_status");
+ if (status != GHB_QUEUE_DONE && status != GHB_QUEUE_RUNNING)
+ {
+ return ii-1;
+ }
+ }
+ return -1;
+}
+
static gint
find_queue_job(GValue *queue, gint unique_id, GValue **job)
{
@@ -3166,7 +3420,7 @@ ghb_backend_events(signal_user_data_t *ud)
queue_buttons_grey(ud, TRUE);
}
index = find_queue_job(ud->queue, status.unique_id, &js);
- if (index >= 0)
+ if (status.unique_id != 0 && index >= 0)
{
gchar working_icon[] = "hb-working0";
working_icon[10] = '0' + working;
@@ -3728,6 +3982,7 @@ pref_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
g_debug("pref_changed_cb");
ghb_widget_to_setting (ud->settings, widget);
+ check_dependency(ud, widget);
const gchar *name = gtk_widget_get_name(widget);
ghb_pref_save(ud->settings, name);
}
@@ -4112,6 +4367,8 @@ ghb_reload_queue(signal_user_data_t *ud)
status = ghb_settings_get_int(settings, "job_status");
if (status == GHB_QUEUE_DONE || status == GHB_QUEUE_CANCELED)
{
+ GValue *old = ghb_array_get_nth(queue, ii);
+ ghb_value_free(old);
ghb_array_remove(queue, ii);
}
}
@@ -4121,7 +4378,7 @@ ghb_reload_queue(signal_user_data_t *ud)
settings = ghb_array_get_nth(queue, ii);
ghb_settings_set_int(settings, "job_unique_id", 0);
ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING);
- add_to_queue_list(ud, settings);
+ add_to_queue_list(ud, settings, NULL);
}
queue_buttons_grey(ud, FALSE);
}