diff options
-rw-r--r-- | gtk/src/ghb.ui | 190 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 2 | ||||
-rw-r--r-- | gtk/src/presets.c | 249 |
3 files changed, 347 insertions, 94 deletions
diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index 32ccd3b1e..5c8ad72dd 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -459,6 +459,57 @@ <column type="gchararray"/> </columns> </object> + + <object class="GtkMenu" id="presets_menu"> + <child> + <object class="GtkImageMenuItem" id="presets_save"> + <property name="label">gtk-save</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="presets_save_clicked_cb"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="presets_remove"> + <property name="label">gtk-delete</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="presets_remove_clicked_cb"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="preset_export"> + <property name="label" translatable="yes">_Export</property> + <property name="use-underline">True</property> + <property name="visible">True</property> + <property name="image">image1</property> + <property name="use_stock">False</property> + <signal name="activate" handler="preset_export_clicked_cb"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="preset_import"> + <property name="label" translatable="yes">_Import</property> + <property name="use-underline">True</property> + <property name="visible">True</property> + <property name="image">image5</property> + <property name="use_stock">False</property> + <signal name="activate" handler="preset_import_clicked_cb"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="presets_restore"> + <property name="label">gtk-refresh</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="presets_restore_clicked_cb"/> + </object> + </child> + </object> + <object class="GtkWindow" id="hb_window"> <property name="visible">True</property> <property name="resizable">False</property> @@ -3472,105 +3523,50 @@ no-dct-decimate=0:cabac=1</property> </object> </child> <child> - <object class="GtkVBox" id="vbox31"> + <object class="GtkToolbar" id="presets_toolbar"> + <property name="icon-size">2</property> <property name="visible">True</property> + <property name="toolbar_style">both-horiz</property> + <property name="show_arrow">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkHBox" id="hbox29"> + <object class="GtkToolButton" id="presets_default"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <property name="is_important">True</property> + <property name="label" translatable="yes">Default</property> + <property name="tooltip-text" translatable="yes">Make the current preset the default.</property> + <property name="icon_name">gtk-apply</property> + <signal handler="presets_default_clicked_cb" name="clicked"/> + </object> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkSeparatorToolItem" id="toolbutton2"> <property name="visible">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <object class="GtkToolButton" id="presets_menu_button"> + <property name="visible">True</property> + <property name="sensitive">True</property> + <property name="is_important">True</property> + <property name="label" translatable="yes">_Options</property> + <property name="use_underline">True</property> + <property name="tooltip-text" translatable="yes">Preset Options</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkButton" id="presets_save"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Save current settings as new preset</property> - <property name="relief">GTK_RELIEF_NONE</property> - <signal handler="presets_save_clicked_cb" name="clicked"/> - <child> - <object class="GtkImage" id="image5"> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - </packing> - </child> - <child> - <object class="GtkButton" id="presets_remove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Remove the selected preset</property> - <property name="relief">GTK_RELIEF_NONE</property> - <signal handler="presets_remove_clicked_cb" name="clicked"/> - <child> - <object class="GtkImage" id="image6"> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label78"> - <property name="width_request">41</property> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - </object> - <packing> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkButton" id="presets_default"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip-text" translatable="yes">Make the current preset the default.</property> - <property name="relief">GTK_RELIEF_NONE</property> - <signal handler="presets_default_clicked_cb" name="clicked"/> - <child> - <object class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="stock">gtk-apply</property> - </object> - </child> - </object> - <packing> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkButton" id="presets_restore"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip-text" translatable="yes">Reload HandBrakes standard presets</property> - <property name="relief">GTK_RELIEF_NONE</property> - <signal handler="presets_restore_clicked_cb" name="clicked"/> - <child> - <object class="GtkImage" id="image7"> - <property name="visible">True</property> - <property name="stock">gtk-refresh</property> - </object> - </child> - </object> - <packing> - <property name="position">4</property> - </packing> - </child> + <property name="icon_name">gtk-execute</property> + <signal handler="presets_menu_clicked_cb" name="clicked"/> </object> + <packing> + <property name="expand">False</property> + </packing> </child> </object> <packing> @@ -6594,4 +6590,12 @@ libx264 authors: <action-widget response="-3">source_ok</action-widget> </action-widgets> </object> + <object class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-save-as</property> + </object> + <object class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + </object> </interface> diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index 86fe2b654..932a50302 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -125,6 +125,8 @@ <false /> <key>default_source</key> <string>/dev/dvd</string> + <key>ExportDirectory</key> + <string></string> <key>destination_dir</key> <string></string> <key>hbfd</key> diff --git a/gtk/src/presets.c b/gtk/src/presets.c index c17a902d4..b536c8aba 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -517,6 +517,37 @@ presets_clear_default(GValue *presets) } } +static void +presets_customize(GValue *presets) +{ + gint count, ii; + + count = ghb_array_len(presets); + for (ii = 0; ii < count; ii++) + { + GValue *dict; + gboolean folder; + gint ptype; + + dict = ghb_array_get_nth(presets, ii); + + ptype = ghb_value_int(preset_dict_get_value(dict, "Type")); + if (ptype != PRESETS_CUSTOM) + { + ghb_dict_insert(dict, g_strdup("Type"), + ghb_int64_value_new(PRESETS_CUSTOM)); + } + folder = ghb_value_boolean(preset_dict_get_value(dict, "Folder")); + if (folder) + { + GValue *nested; + + nested = ghb_dict_lookup(dict, "ChildrenArray"); + presets_customize(nested); + } + } +} + static gint* presets_find_default2(GValue *presets, gint *len) { @@ -1385,13 +1416,23 @@ ghb_prefs_load(signal_user_data_t *ud) { ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval)); } - const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); + + const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); + if (dir == NULL) + { + dir = "."; + } + ghb_dict_insert(dict, + g_strdup("ExportDirectory"), ghb_value_dup(ghb_string_value(dir))); + + dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); if (dir == NULL) { dir = "."; } ghb_dict_insert(dict, g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir))); + ghb_dict_insert(dict, g_strdup("SrtDir"), ghb_value_dup(ghb_string_value(dir))); #if defined(_WIN32) @@ -3115,6 +3156,212 @@ enforce_preset_type(signal_user_data_t *ud, const GValue *path) } G_MODULE_EXPORT void +presets_menu_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + GtkMenu *menu; + + menu = GTK_MENU(GHB_WIDGET(ud->builder, "presets_menu")); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 1, + gtk_get_current_event_time()); +} + +G_MODULE_EXPORT void +preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + GtkWidget *dialog; + GtkResponseType response; + gchar *exportDir; + gchar *filename; + GtkFileFilter *filter; + + g_debug("preset_import_clicked_cb ()"); + + dialog = gtk_file_chooser_dialog_new("Export Preset", NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, "All (*)"); + gtk_file_filter_add_pattern(filter, "*"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, "Presets (*.plist)"); + gtk_file_filter_add_pattern(filter, "*.plist"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + if (exportDir == NULL || exportDir[0] == '\0') + { + exportDir = g_strdup("."); + } + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), exportDir); + g_free(exportDir); + + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response == GTK_RESPONSE_ACCEPT) + { + GValue *dict, *array; + gchar *dir; + gint count, ii; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + // import the preset + if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + { + gtk_widget_destroy(dialog); + g_free(filename); + return; + } + array = ghb_plist_parse_file(filename); + g_free(filename); + + import_xlat_presets(array); + presets_clear_default(array); + presets_customize(array); + + count = ghb_array_len(array); + for (ii = 0; ii < count; ii++) + { + GValue *path, *name; + gint *indices, len; + gint index = 1; + + dict = ghb_array_get_nth(array, ii); + path = ghb_array_value_new(1); + name = ghb_value_dup(ghb_dict_lookup(dict, "PresetName")); + ghb_array_append(path, name); + indices = ghb_preset_indices_from_path(presetsPlist, path, &len); + // Modify the preset name till we make it unique + while (indices != NULL) + { + gchar *str = ghb_value_string(name); + + ghb_value_free(path); + g_free(indices); + + str = g_strdup_printf("%s %d", str, index); + path = ghb_array_value_new(1); + name = ghb_string_value_new(str); + ghb_array_append(path, name); + g_free(str); + + index++; + indices = ghb_preset_indices_from_path(presetsPlist, path, &len); + } + ghb_dict_insert(dict, g_strdup("PresetName"), ghb_value_dup(name)); + indices = presets_find_pos(path, PRESETS_CUSTOM, &len); + ghb_presets_insert(presetsPlist, ghb_value_dup(dict), indices, len); + presets_list_insert(ud, indices, len); + ghb_value_free(path); + } + ghb_value_free(array); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + dir = g_path_get_dirname(filename); + if (strcmp(dir, exportDir) != 0) + { + ghb_settings_set_string(ud->settings, "ExportDirectory", dir); + ghb_pref_save(ud->settings, "ExportDirectory"); + } + g_free(exportDir); + g_free(dir); + } + gtk_widget_destroy(dialog); +} + +G_MODULE_EXPORT void +preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + GtkWidget *dialog; + GtkResponseType response; + GValue *preset; + const gchar *name = ""; + gint count, *indices, len; + gchar *exportDir; + gchar *filename; + + g_debug("preset_export_clicked_cb ()"); + preset = ghb_settings_get_value (ud->settings, "preset_selection"); + if (preset == NULL) + return; + + count = ghb_array_len(preset); + if (count <= 0) + return; + + name = g_value_get_string(ghb_array_get_nth(preset, count-1)); + + dialog = gtk_file_chooser_dialog_new("Export Preset", NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + if (exportDir == NULL || exportDir[0] == '\0') + { + exportDir = g_strdup("."); + } + filename = g_strdup_printf("%s.plist", name); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), exportDir); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); + g_free(filename); + g_free(exportDir); + + indices = ghb_preset_indices_from_path(presetsPlist, preset, &len); + if (indices == NULL) + return; + + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response == GTK_RESPONSE_ACCEPT) + { + GValue *export, *dict, *array; + FILE *file; + gchar *dir; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + // export the preset + dict = presets_get_dict(presetsPlist, indices, len); + + export = ghb_value_dup(dict); + array = ghb_array_value_new(1); + ghb_array_append(array, export); + presets_clear_default(array); + presets_customize(array); + export_xlat_presets(array); + + file = g_fopen(filename, "w"); + if (file != NULL) + { + ghb_plist_write(file, array); + fclose(file); + } + ghb_value_free(array); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + dir = g_path_get_dirname(filename); + if (strcmp(dir, exportDir) != 0) + { + ghb_settings_set_string(ud->settings, "ExportDirectory", dir); + ghb_pref_save(ud->settings, "ExportDirectory"); + } + g_free(exportDir); + g_free(dir); + g_free(filename); + } + gtk_widget_destroy(dialog); + g_free(indices); +} + +G_MODULE_EXPORT void presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GtkWidget *dialog; |