diff options
author | jstebbins <[email protected]> | 2014-02-22 03:01:15 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2014-02-22 03:01:15 +0000 |
commit | ab50e34327aea45ed0a1b258d07bd269dcc39a9e (patch) | |
tree | a848a75d05e42a0ea5ca493d286e22f8f936ed7b /gtk/src | |
parent | e334a91396d51f1c22648f27c32492101a3053b5 (diff) |
LinGui: add dialog to select multiple titles to add to queue
Replaces "Add All to Queue".
Dialog provides checkboxes to select titles to add to the queue and file
chooser/file entry to change destination file names.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6056 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'gtk/src')
-rw-r--r-- | gtk/src/audiohandler.c | 29 | ||||
-rw-r--r-- | gtk/src/callbacks.c | 30 | ||||
-rw-r--r-- | gtk/src/callbacks.h | 1 | ||||
-rw-r--r-- | gtk/src/ghb.ui | 224 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 104 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 1 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 2 | ||||
-rw-r--r-- | gtk/src/makedeps.py | 2 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 525 | ||||
-rw-r--r-- | gtk/src/queuehandler.h | 1 |
10 files changed, 815 insertions, 104 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c index d5ae66f3f..ec889a013 100644 --- a/gtk/src/audiohandler.c +++ b/gtk/src/audiohandler.c @@ -1596,7 +1596,8 @@ static void audio_def_update_widgets(GtkWidget *row, GValue *adict) block_updates = FALSE; } -GtkListBoxRow * ghb_audio_settings_get_row(GtkWidget *widget) +static GtkListBoxRow* +audio_settings_get_row(GtkWidget *widget) { while (widget != NULL && G_OBJECT_TYPE(widget) != GTK_TYPE_LIST_BOX_ROW) { @@ -1959,7 +1960,7 @@ GtkWidget * ghb_create_audio_settings_row(signal_user_data_t *ud) static void audio_def_setting_update(signal_user_data_t *ud, GtkWidget *widget) { - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); gint index = gtk_list_box_row_get_index(row); GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); @@ -2061,7 +2062,7 @@ static void audio_quality_update_limits(GtkWidget *widget, int encoder) void audio_def_set_limits(signal_user_data_t *ud, GtkWidget *widget) { - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); gint index = gtk_list_box_row_get_index(row); GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); @@ -2148,7 +2149,7 @@ audio_def_quality_enable_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { audio_def_setting_update(ud, widget); - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); gint index = gtk_list_box_row_get_index(row); GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); @@ -2164,7 +2165,7 @@ audio_def_quality_changed_cb(GtkWidget *widget, gdouble quality, signal_user_dat { audio_def_setting_update(ud, widget); - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); GtkWidget *quality_label = find_widget(GTK_WIDGET(row), "AudioTrackQualityValue"); gint index = gtk_list_box_row_get_index(row); @@ -2192,7 +2193,7 @@ audio_def_gain_changed_cb(GtkWidget *widget, gdouble gain, signal_user_data_t *u { audio_def_setting_update(ud, widget); - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); GtkWidget *gain_label = find_widget(GTK_WIDGET(row), "AudioTrackGainValue"); char *s_gain; if ( gain >= 21.0 ) @@ -2209,7 +2210,7 @@ audio_def_drc_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud) { audio_def_setting_update(ud, widget); - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); GtkWidget *drc_label = find_widget(GTK_WIDGET(row), "AudioTrackDRCValue"); char *s_drc; @@ -2225,7 +2226,7 @@ audio_def_drc_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud) G_MODULE_EXPORT void audio_def_setting_add_cb(GtkWidget *widget, signal_user_data_t *ud) { - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); GValue *adict; GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); @@ -2257,7 +2258,7 @@ audio_def_setting_add_cb(GtkWidget *widget, signal_user_data_t *ud) G_MODULE_EXPORT void audio_def_setting_remove_cb(GtkWidget *widget, signal_user_data_t *ud) { - GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkListBoxRow *row = audio_settings_get_row(widget); gint index = gtk_list_box_row_get_index(row); GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); @@ -2281,16 +2282,6 @@ audio_def_encode_setting_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_clear_presets_selection(ud); } -static void container_empty_cb(GtkWidget *widget, gpointer data) -{ - gtk_widget_destroy(widget); -} - -void ghb_container_empty(GtkContainer *c) -{ - gtk_container_foreach(c, container_empty_cb, NULL); -} - GtkListBoxRow* ghb_find_lang_row(GtkListBox *list_box, int lang_idx) { GList *list, *link; diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index d22254339..e288db2d8 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -1866,22 +1866,6 @@ load_all_titles(signal_user_data_t *ud, int titleindex) ud->settings = ghb_array_get_nth(ud->settings_array, titleindex); } -void -ghb_add_all_titles(signal_user_data_t *ud) -{ - gint ii; - gint count; - - 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)); - ghb_queue_add(ud, settings, ii); - } -} - static gboolean update_preview = FALSE; G_MODULE_EXPORT void @@ -2908,8 +2892,8 @@ ghb_backend_events(signal_user_data_t *ud) GtkTreeView *treeview; GtkTreeStore *store; GtkTreeIter iter; - static gint prev_scan_state = 0; - static gint prev_queue_state = 0; + static gint prev_scan_state = -1; + static gint prev_queue_state = -1; ghb_track_status(); ghb_get_status(&status); @@ -5282,3 +5266,13 @@ window_configure_cb( return FALSE; } +static void container_empty_cb(GtkWidget *widget, gpointer data) +{ + gtk_widget_destroy(widget); +} + +void ghb_container_empty(GtkContainer *c) +{ + gtk_container_foreach(c, container_empty_cb, NULL); +} + diff --git a/gtk/src/callbacks.h b/gtk/src/callbacks.h index 9b794294c..25ba5a56b 100644 --- a/gtk/src/callbacks.h +++ b/gtk/src/callbacks.h @@ -81,6 +81,7 @@ void ghb_update_title_info(signal_user_data_t *ud); void ghb_chapter_list_refresh_all(signal_user_data_t *ud); void ghb_load_settings(signal_user_data_t * ud); void ghb_set_current_title_settings(signal_user_data_t *ud); +void ghb_container_empty(GtkContainer *c); #endif // _CALLBACKS_H_ diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index cb938aa8f..dc4cdc66c 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -681,7 +681,7 @@ libx264 authors: <property name="can_focus">False</property> <child> <object class="GtkMenuItem" id="queue_add_menu"> - <property name="label" translatable="yes">_Add Queue</property> + <property name="label" translatable="yes">_Add</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> @@ -689,17 +689,17 @@ libx264 authors: </object> </child> <child> - <object class="GtkMenuItem" id="queue_add_all_menu"> - <property name="label" translatable="yes">Add A_ll Queue</property> + <object class="GtkMenuItem" id="queue_add_multiple_menu"> + <property name="label" translatable="yes">Add _Multiple</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> - <signal name="activate" handler="queue_add_all_clicked_cb" swapped="no"/> + <signal name="activate" handler="queue_add_multiple_clicked_cb" swapped="no"/> </object> </child> <child> <object class="GtkMenuItem" id="queue_start_menu"> - <property name="label" translatable="yes">_Start Queue</property> + <property name="label" translatable="yes">_Start</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> @@ -708,7 +708,7 @@ libx264 authors: </child> <child> <object class="GtkMenuItem" id="queue_pause_menu"> - <property name="label" translatable="yes">_Pause Queue</property> + <property name="label" translatable="yes">_Pause</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> @@ -3270,6 +3270,8 @@ All other secondary audio output tracks will be encoded with first encoder only. <property name="visible">True</property> <property name="can_focus">False</property> <property name="vexpand">True</property> + <property name="selection_mode">none</property> + <property name="activate_on_single_click">False</property> </object> </child> </object> @@ -5577,6 +5579,204 @@ You can edit these and add additional options.</property> <property name="step_increment">5</property> <property name="page_increment">10</property> </object> + <object class="GtkDialog" id="titla_add_multiple_dialog"> + <property name="can_focus">False</property> + <property name="type_hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog_title_add_multiple_vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog_title_add_multiple_action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="title_add_multiple_cancel"> + <property name="label">gtk-cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="title_add_multiple_ok"> + <property name="label">gtk-ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="yalign">0.55000001192092896</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="title_add_multiple_grid1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">12</property> + <property name="margin_right">12</property> + <property name="margin_top">12</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkScrolledWindow" id="title_add_multiple_scrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="min_content_height">400</property> + <child> + <object class="GtkListBox" id="title_add_multiple_list"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="vexpand">True</property> + <property name="hexpand">True</property> + <property name="selection_mode">none</property> + <property name="activate_on_single_click">False</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + <property name="width">3</property> + <property name="height">2</property> + </packing> + </child> + <child> + <object class="GtkBox" id="title_add_multiple_hbox1"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkCheckButton" id="title_add_multiple_select_all"> + <property name="label" translatable="yes">Select All</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Mark all titles for adding to the queue</property> + <property name="halign">start</property> + <property name="vexpand">False</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="title_add_multiple_select_all_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="title_add_multiple_clear_all"> + <property name="label" translatable="yes">Clear All</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Unmark all titles</property> + <property name="halign">start</property> + <property name="vexpand">False</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="title_add_multiple_clear_all_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">2</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkInfoBar" id="title_add_multiple_infobar"> + <property name="visible">True</property> + <property name="app_paintable">True</property> + <property name="can_focus">False</property> + <property name="message_type">info</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="title_add_multiple_infobar-action_area1"> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <property name="layout_style">end</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child internal-child="content_area"> + <object class="GtkBox" id="title_add_multiple_infobar_content_area"> + <property name="can_focus">False</property> + <property name="spacing">16</property> + <child> + <object class="GtkLabel" id="title_add_multiple_label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Destination files OK. No duplicates detected.</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + <property name="width">3</property> + <property name="height">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">title_add_multiple_cancel</action-widget> + <action-widget response="-5">title_add_multiple_ok</action-widget> + </action-widgets> + </object> <object class="GtkDialog" id="prefs_dialog"> <property name="can_focus">False</property> <property name="border_width">5</property> @@ -9098,10 +9298,11 @@ YadifMode:YadifParity:McdintMode:McdeintQp</property> <property name="layout_style">end</property> <child> <object class="GtkButton" id="subtitle_cancel"> - <property name="label" translatable="yes">Cancel</property> + <property name="label">gtk-cancel</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_stock">True</property> </object> <packing> <property name="expand">False</property> @@ -9111,10 +9312,11 @@ YadifMode:YadifParity:McdintMode:McdeintQp</property> </child> <child> <object class="GtkButton" id="subtitle_ok"> - <property name="label" translatable="yes">Ok</property> + <property name="label">gtk-ok</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_stock">True</property> </object> <packing> <property name="expand">False</property> @@ -9483,10 +9685,11 @@ in your output.</property> <property name="layout_style">end</property> <child> <object class="GtkButton" id="audio_cancel"> - <property name="label" translatable="yes">Cancel</property> + <property name="label">gtk-cancel</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_stock">True</property> </object> <packing> <property name="expand">False</property> @@ -9496,10 +9699,11 @@ in your output.</property> </child> <child> <object class="GtkButton" id="audio_ok"> - <property name="label" translatable="yes">Ok</property> + <property name="label">gtk-ok</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_stock">True</property> </object> <packing> <property name="expand">False</property> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index ae09f6dc4..0a4a3266c 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -2058,6 +2058,61 @@ language_opts_set(GtkBuilder *builder, const gchar *name) static gchar **titles = NULL; +gchar* +ghb_create_title_label(hb_title_t *title) +{ + gchar *label; + + if (title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE) + { + if (title->duration != 0) + { + char *tmp; + tmp = g_strdup_printf ("%d - %02dh%02dm%02ds - %s", + title->index, title->hours, title->minutes, title->seconds, + title->name); + label = g_markup_escape_text(tmp, -1); + g_free(tmp); + } + else + { + char *tmp; + tmp = g_strdup_printf ("%d - %s", + title->index, title->name); + label = g_markup_escape_text(tmp, -1); + g_free(tmp); + } + } + else if (title->type == HB_BD_TYPE) + { + if (title->duration != 0) + { + label = g_strdup_printf("%d (%05d.MPLS) - %02dh%02dm%02ds", + title->index, title->playlist, title->hours, + title->minutes, title->seconds); + } + else + { + label = g_strdup_printf("%d (%05d.MPLS) - Unknown Length", + title->index, title->playlist); + } + } + else + { + if (title->duration != 0) + { + label = g_strdup_printf("%d - %02dh%02dm%02ds", + title->index, title->hours, title->minutes, title->seconds); + } + else + { + label = g_strdup_printf("%d - Unknown Length", + title->index); + } + } + return label; +} + void title_opts_set(GtkBuilder *builder, const gchar *name) { @@ -2111,53 +2166,8 @@ title_opts_set(GtkBuilder *builder, const gchar *name) for (ii = 0; ii < count; ii++) { title = (hb_title_t*)hb_list_item(list, ii); - if (title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE) - { - if (title->duration != 0) - { - char *tmp; - tmp = g_strdup_printf ("%d - %02dh%02dm%02ds - %s", - title->index, title->hours, title->minutes, title->seconds, - title->name); - titles[ii] = g_markup_escape_text(tmp, -1); - g_free(tmp); - } - else - { - char *tmp; - tmp = g_strdup_printf ("%d - %s", - title->index, title->name); - titles[ii] = g_markup_escape_text(tmp, -1); - g_free(tmp); - } - } - else if (title->type == HB_BD_TYPE) - { - if (title->duration != 0) - { - titles[ii] = g_strdup_printf("%d (%05d.MPLS) - %02dh%02dm%02ds", - title->index, title->playlist, title->hours, - title->minutes, title->seconds); - } - else - { - titles[ii] = g_strdup_printf("%d (%05d.MPLS) - Unknown Length", - title->index, title->playlist); - } - } - else - { - if (title->duration != 0) - { - titles[ii] = g_strdup_printf("%d - %02dh%02dm%02ds", - title->index, title->hours, title->minutes, title->seconds); - } - else - { - titles[ii] = g_strdup_printf("%d - Unknown Length", - title->index); - } - } + titles[ii] = ghb_create_title_label(title); + gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, titles[ii], diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 8311de9a2..0f15d4070 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -171,5 +171,6 @@ void ghb_audio_samplerate_opts_set(GtkComboBox *combo); int ghb_lookup_audio_lang(const GValue *glang); const iso639_lang_t* ghb_iso639_lookup_by_int(int idx); void ghb_update_display_aspect_label(signal_user_data_t *ud); +gchar* ghb_create_title_label(hb_title_t *title); #endif // _HBBACKEND_H_ diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index e1c2eaef4..2959e4945 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -77,6 +77,8 @@ <integer>0</integer> <key>title</key> <string>none</string> + <key>title_selected</key> + <false /> <key>volume_label</key> <string>New Video</string> <key>audio_list</key> diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py index 7be7a71b5..aa2111cea 100644 --- a/gtk/src/makedeps.py +++ b/gtk/src/makedeps.py @@ -8,7 +8,7 @@ DepEntry = collections.namedtuple('DepEntry', 'widget dep enable die hide') dep_map = ( DepEntry("title", "queue_add", "none", True, False), DepEntry("title", "queue_add_menu", "none", True, False), - DepEntry("title", "queue_add_all_menu", "none", True, False), + DepEntry("title", "queue_add_multiple_menu", "none", True, False), DepEntry("title", "preview_frame", "none", True, False), DepEntry("title", "picture_summary", "none", True, False), DepEntry("title", "picture_summary2", "none", True, False), 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; diff --git a/gtk/src/queuehandler.h b/gtk/src/queuehandler.h index abf33757a..e91a2f241 100644 --- a/gtk/src/queuehandler.h +++ b/gtk/src/queuehandler.h @@ -30,6 +30,5 @@ void ghb_queue_buttons_grey(signal_user_data_t *ud); gboolean ghb_reload_queue(signal_user_data_t *ud); -gboolean ghb_queue_add(signal_user_data_t *ud, GValue *settings, gint batch); #endif // _QUEUEHANDLER_H_ |