]> granicus.if.org Git - handbrake/commitdiff
LinGui: add dialog to select multiple titles to add to queue
authorjstebbins <jstebbins.hb@gmail.com>
Sat, 22 Feb 2014 03:01:15 +0000 (03:01 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Sat, 22 Feb 2014 03:01:15 +0000 (03:01 +0000)
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

gtk/src/audiohandler.c
gtk/src/callbacks.c
gtk/src/callbacks.h
gtk/src/ghb.ui
gtk/src/hb-backend.c
gtk/src/hb-backend.h
gtk/src/internal_defaults.xml
gtk/src/makedeps.py
gtk/src/queuehandler.c
gtk/src/queuehandler.h

index d5ae66f3f851dd8a9c6bbfba7c20b781ba40fc45..ec889a013966c9dd39bdab7fd203eedf4002fbff 100644 (file)
@@ -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;
index d2225433995279f3c18580c573f3bfe87a247d0c..e288db2d810688e7e782ac027f3f57c9d93f23af 100644 (file)
@@ -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);
+}
+
index 9b794294cb81c1e132625c0453c29e11702a083e..25ba5a56b3085d2723f84b45707a42f9167d9ad6 100644 (file)
@@ -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_
 
index cb938aa8f6ddb6632a1829bdbc70125a72044fa5..dc4cdc66c2bce626f99d137b6c56185ce37be4b1 100644 (file)
@@ -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>
index ae09f6dc41c75a3656c57505408209c2cc201831..0a4a3266c334e0bf9aabf35e4acd8395974f3c18 100644 (file)
@@ -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],
index 8311de9a2890702093b24a70cf872b97765985c0..0f15d4070f74e0daebde81e3e3a0a69718bdbd55 100644 (file)
@@ -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_
index e1c2eaef4548e443c925950ea0930bedf798f39a..2959e4945f8815b6c7fb09c2756cad6f23abf913 100644 (file)
@@ -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>
index 7be7a71b5724a5811e6114b33f5b2c78c118ad0b..aa2111cea65eeef1cfb6a56bbe738f6b05a976b3 100644 (file)
@@ -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),
index 507b3cc08b17937a0bb1089ed30e5c6d1d56fb68..847eacd6d783f76dbd9bffbcc1ad0c0a8bd10a68 100644 (file)
@@ -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;
index abf33757a94bf2d0fac4e51c560dfd0a94fe27d6..e91a2f241f486925b95b435795e91d44666467ea 100644 (file)
@@ -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_