summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/callbacks.c12
-rw-r--r--gtk/src/ghb.m4106
-rw-r--r--gtk/src/hb-backend.c72
-rw-r--r--gtk/src/internal_defaults.json1
-rw-r--r--gtk/src/main.c5
-rw-r--r--gtk/src/makedeps.py2
-rw-r--r--gtk/src/presets.c409
-rw-r--r--gtk/src/presets.h2
-rw-r--r--libhb/preset.c35
-rw-r--r--libhb/preset.h12
-rw-r--r--test/test.c3
11 files changed, 407 insertions, 252 deletions
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c
index c2f709f18..db31cd2e1 100644
--- a/gtk/src/callbacks.c
+++ b/gtk/src/callbacks.c
@@ -1175,15 +1175,17 @@ check_chapter_markers(signal_user_data_t *ud)
void
ghb_load_settings(signal_user_data_t * ud)
{
- const char *fullname;
- gboolean preset_modified;
- static gboolean busy = FALSE;
+ const char * fullname;
+ int type;
+ gboolean preset_modified;
+ static gboolean busy = FALSE;
if (busy)
return;
busy = TRUE;
- fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
+ fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
+ type = ghb_dict_get_int(ud->settings, "Type");
preset_modified = ghb_dict_get_bool(ud->settings, "preset_modified");
if (preset_modified)
{
@@ -1192,7 +1194,7 @@ ghb_load_settings(signal_user_data_t * ud)
else
{
ghb_dict_set_bool(ud->settings, "preset_reload", TRUE);
- ghb_select_preset(ud, fullname);
+ ghb_select_preset(ud, fullname, type);
ghb_dict_set_bool(ud->settings, "preset_reload", FALSE);
}
diff --git a/gtk/src/ghb.m4 b/gtk/src/ghb.m4
index f93e593d1..c4c2f04fe 100644
--- a/gtk/src/ghb.m4
+++ b/gtk/src/ghb.m4
@@ -147,15 +147,6 @@ conjunction with the "Forced" option.</property>
</object>
</child>
<child>
- <object class="GtkMenuItem" id="presets_window_new_folder">
- <property name="label" translatable="yes">_New Folder</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="action-name">app.preset-folder</property>
- </object>
- </child>
- <child>
<object class="GtkMenuItem" id="presets_window_export">
<property name="label" translatable="yes">_Export</property>
<property name="visible">True</property>
@@ -959,15 +950,6 @@ libx264 authors:
</object>
</child>
<child>
- <object class="GtkMenuItem" id="presets_new_folder">
- <property name="label" translatable="yes">_New Folder</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="action-name">app.preset-folder</property>
- </object>
- </child>
- <child>
<object class="GtkMenuItem" id="presets_export">
<property name="label" translatable="yes">_Export</property>
<property name="visible">True</property>
@@ -8378,23 +8360,91 @@ Check this if you want the queue to clean itself up by deleting completed jobs.<
<property name="can_focus">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="GtkBox" id="hbox41">
- <property name="orientation">horizontal</property>
+ <object class="GtkGrid" id="preset_save_name_table">
<property name="visible">True</property>
+ <property name="row-spacing">2</property>
+ <property name="column-spacing">6</property>
<property name="can_focus">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="GtkLabel" id="preset_save_category_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Category:</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="PresetCategory">
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</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">Set the category that this preset will be shown under.</property>
+ <signal name="changed" handler="preset_category_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="PresetCategoryEntryLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Category Name:</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="PresetCategoryName">
+ <property name="visible">True</property>
+ <property name="can_focus">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="max_length">40</property>
+ <property name="activates_default">True</property>
+ <property name="width-chars">30</property>
+ <property name="truncate_multiline">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <signal name="changed" handler="preset_category_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkLabel" id="label64">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="halign">start</property>
+ <property name="halign">end</property>
<property name="label" translatable="yes">Preset Name:</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
@@ -8408,11 +8458,13 @@ Check this if you want the queue to clean itself up by deleting completed jobs.<
<property name="truncate_multiline">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
+ <signal name="changed" handler="preset_name_changed_cb" swapped="no"/>
</object>
<packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
</object>
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c
index c38835959..3f7b1fd68 100644
--- a/gtk/src/hb-backend.c
+++ b/gtk/src/hb-backend.c
@@ -457,6 +457,8 @@ static void video_level_opts_set(signal_user_data_t *ud, const gchar *name,
void *opts, const void* data);
static void container_opts_set(signal_user_data_t *ud, const gchar *name,
void *opts, const void* data);
+static void preset_category_opts_set(signal_user_data_t *ud, const gchar *name,
+ void *opts, const void* data);
static void filter_opts_set(signal_user_data_t *ud, const gchar *name,
void *opts, const void* data);
static void deint_opts_set(signal_user_data_t *ud, const gchar *name,
@@ -749,6 +751,12 @@ combo_name_map_t combo_name_map[] =
container_opts_set,
NULL
},
+ {
+ "PresetCategory",
+ NULL,
+ preset_category_opts_set,
+ NULL
+ },
{NULL, NULL, NULL, NULL}
};
@@ -1899,6 +1907,70 @@ container_opts_set(signal_user_data_t *ud, const gchar *name,
}
}
+static void
+preset_category_opts_set(signal_user_data_t *ud, const gchar *name,
+ void *opts, const void* data)
+{
+ (void)opts; // Silence "unused variable" warning
+ (void)data; // Silence "unused variable" warning
+ GtkTreeIter iter;
+ GtkListStore * store;
+ gint ii, jj, count;
+ hb_value_t * presets;
+ GtkComboBox * combo;
+ char ** categories;
+
+ presets = hb_presets_get();
+ count = hb_value_array_len(presets);
+
+ combo = GTK_COMBO_BOX(GHB_WIDGET(ud->builder, name));
+ store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
+ gtk_list_store_clear(store);
+
+ categories = calloc(count + 1, sizeof(char*));
+ for (ii = 0, jj = 0; ii < count; ii++)
+ {
+ const char * name;
+ hb_value_t * folder = hb_value_array_get(presets, ii);
+
+ if (!hb_value_get_bool(hb_dict_get(folder, "Folder")))
+ {
+ // Only list folders
+ continue;
+ }
+
+ name = hb_value_get_string(hb_dict_get(folder, "PresetName"));
+ if (name == NULL || name[0] == 0)
+ {
+ continue;
+ }
+
+ if (g_strv_contains((const char**)categories, name))
+ {
+ // Category is already in the list
+ continue;
+ }
+
+ categories[jj++] = g_strdup(name);
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, name,
+ 1, TRUE,
+ 2, name,
+ 3, (gdouble)ii,
+ -1);
+ }
+ g_strfreev(categories);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, "Add New Category",
+ 1, TRUE,
+ 2, "new",
+ 3, -1.0,
+ -1);
+}
+
const hb_container_t*
ghb_lookup_container_by_name(const gchar *name)
{
diff --git a/gtk/src/internal_defaults.json b/gtk/src/internal_defaults.json
index be47bfbc4..77a5df2c3 100644
--- a/gtk/src/internal_defaults.json
+++ b/gtk/src/internal_defaults.json
@@ -41,6 +41,7 @@
"MetaDescription": "",
"MetaLongDescription": "",
"PresetFullName": "/Regular/Normal",
+ "PresetCategory": "new",
"preset_modified": false,
"preset_reload": false,
"PictureDisplayWidth": 720,
diff --git a/gtk/src/main.c b/gtk/src/main.c
index aacb72d5c..8270a58f5 100644
--- a/gtk/src/main.c
+++ b/gtk/src/main.c
@@ -861,8 +861,6 @@ preset_remove_action_cb(GSimpleAction *action, GVariant *param, gpointer ud);
G_MODULE_EXPORT void
preset_default_action_cb(GSimpleAction *action, GVariant *param, gpointer ud);
G_MODULE_EXPORT void
-preset_folder_action_cb(GSimpleAction *action, GVariant *param, gpointer ud);
-G_MODULE_EXPORT void
preset_export_action_cb(GSimpleAction *action, GVariant *param, gpointer ud);
G_MODULE_EXPORT void
preset_import_action_cb(GSimpleAction *action, GVariant *param, gpointer ud);
@@ -904,7 +902,6 @@ static void map_actions(GApplication * app, signal_user_data_t * ud)
{ "preset-save", preset_save_action_cb },
{ "preset-remove", preset_remove_action_cb },
{ "preset-default", preset_default_action_cb },
- { "preset-folder", preset_folder_action_cb },
{ "preset-export", preset_export_action_cb },
{ "preset-import", preset_import_action_cb },
{ "presets-reload", presets_reload_action_cb },
@@ -940,7 +937,7 @@ ghb_idle_ui_init(signal_user_data_t *ud)
if (arg_preset != NULL)
{
- ghb_select_preset(ud, arg_preset);
+ ghb_select_preset(ud, arg_preset, HB_PRESET_TYPE_ALL);
}
else
{
diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py
index 759898400..69606aa84 100644
--- a/gtk/src/makedeps.py
+++ b/gtk/src/makedeps.py
@@ -65,6 +65,8 @@ dep_map = (
DepEntry("VideoEncoder", "x264_box", "x264|x264_10bit", False, True),
DepEntry("x264UseAdvancedOptions", "x264_box", "0", True, False),
DepEntry("auto_name", "autoname_box", "1", False, False),
+ DepEntry("PresetCategory", "PresetCategoryName", "new", False, True),
+ DepEntry("PresetCategory", "PresetCategoryEntryLabel", "new", False, True),
)
def main():
diff --git a/gtk/src/presets.c b/gtk/src/presets.c
index 955d9f9db..87ca95860 100644
--- a/gtk/src/presets.c
+++ b/gtk/src/presets.c
@@ -45,13 +45,6 @@
#define MAX_NESTED_PRESET 3
-enum
-{
- PRESETS_INVALID = -1,
- PRESETS_BUILTIN = 0,
- PRESETS_CUSTOM
-};
-
static GhbValue *prefsDict = NULL;
static gboolean prefs_modified = FALSE;
static gchar *override_user_config_dir = NULL;
@@ -622,11 +615,11 @@ select_preset2(signal_user_data_t *ud, hb_preset_index_t *path)
}
void
-ghb_select_preset(signal_user_data_t *ud, const char *name)
+ghb_select_preset(signal_user_data_t *ud, const char *name, int type)
{
hb_preset_index_t *path;
- path = hb_preset_search_index(name, 1);
+ path = hb_preset_search_index(name, 1, type);
if (path != NULL)
{
select_preset2(ud, path);
@@ -1110,7 +1103,7 @@ get_preset_color(gint type, gboolean is_folder)
{
const gchar *color;
- if (type == PRESETS_CUSTOM)
+ if (type == HB_PRESET_TYPE_CUSTOM)
{
color = "DimGray";
if (is_folder)
@@ -1150,9 +1143,10 @@ G_MODULE_EXPORT void
preset_select_action_cb(GSimpleAction *action, GVariant *param,
signal_user_data_t *ud)
{
- const char * preset_path = g_variant_get_string(param, NULL);
+ const char * preset_path = g_variant_get_string(param, NULL);
+ int type = preset_path[0] - '0';
- ghb_select_preset(ud, preset_path);
+ ghb_select_preset(ud, &preset_path[1], type);
}
G_MODULE_EXPORT void
@@ -1160,21 +1154,24 @@ preset_reload_action_cb(GSimpleAction *action, GVariant *param,
signal_user_data_t *ud)
{
const char * preset_path;
+ int type;
+ type = ghb_dict_get_int(ud->settings, "Type");
preset_path = ghb_dict_get_string(ud->settings, "PresetFullName");
if (preset_path != NULL)
{
- ghb_select_preset(ud, preset_path);
+ ghb_select_preset(ud, preset_path, type);
}
}
void
ghb_presets_menu_init(signal_user_data_t *ud)
{
- GMenu * menu = g_menu_new();
- hb_preset_index_t * path;
- GhbValue * presets;
- int menu_count, submenu_count, type, ii, jj;
+ GMenu * menu = g_menu_new();
+ hb_preset_index_t * path;
+ GhbValue * presets;
+ int menu_count, submenu_count, type, ii, jj, kk;
+ char ** official_names;
// Add official presets
path = hb_preset_index_init(NULL, 0);
@@ -1187,6 +1184,11 @@ ghb_presets_menu_init(signal_user_data_t *ud)
}
menu_count = ghb_array_len(presets);
+ // Menus can't contain the same name twice. Since our preset list
+ // allows official and custom preset categories with the same name
+ // I must modify one of them when duplicates exist :(
+ official_names = calloc(menu_count + 1, sizeof(char*));
+ kk = 0;
path->depth++;
// Process Official Presets in first pass, then Custom Presets
for (type = 0; type < 2; type++)
@@ -1200,6 +1202,7 @@ ghb_presets_menu_init(signal_user_data_t *ud)
gboolean is_folder;
GhbValue * folder;
GString * folder_str;
+ char * menu_item_name;
path->index[path->depth-1] = ii;
@@ -1213,8 +1216,15 @@ ghb_presets_menu_init(signal_user_data_t *ud)
continue;
}
+ if (type == 0)
+ {
+ // Add folder name to list of official names
+ official_names[kk++] = g_strdup(folder_name);
+ }
+
folder_str = g_string_new("");
- g_string_append_printf(folder_str, "/%s", folder_name);
+ g_string_append_printf(folder_str, "%d/%s",
+ folder_type, folder_name);
if (is_folder)
{
GMenu * submenu = g_menu_new();
@@ -1252,14 +1262,25 @@ ghb_presets_menu_init(signal_user_data_t *ud)
g_menu_append(submenu, name, detail_action);
free(preset_path);
}
- g_menu_append_submenu(section, folder_name,
+ if (type == 1 &&
+ g_strv_contains((const char**)official_names, folder_name))
+ {
+ menu_item_name = g_strdup_printf("My %s", folder_name);
+ }
+ else
+ {
+ menu_item_name = g_strdup(folder_name);
+ }
+ g_menu_append_submenu(section, menu_item_name,
G_MENU_MODEL(submenu));
+ g_free(menu_item_name);
}
g_string_free(folder_str, TRUE);
}
g_menu_append_section(menu, type ? "Custom" : "Official",
G_MENU_MODEL(section));
}
+ g_strfreev(official_names);
GtkMenuButton * mb;
@@ -1357,7 +1378,7 @@ ghb_presets_list_init(signal_user_data_t *ud, const hb_preset_index_t *path)
2, def ? 2 : 0,
3, color,
4, description,
- 5, type == PRESETS_BUILTIN ? 0 : 1,
+ 5, type == HB_PRESET_TYPE_OFFICIAL ? 0 : 1,
-1);
if (is_folder)
{
@@ -1444,7 +1465,7 @@ presets_list_update_item(
2, def ? 2 : 0,
3, color,
4, description,
- 5, type == PRESETS_BUILTIN ? 0 : 1,
+ 5, type == HB_PRESET_TYPE_OFFICIAL ? 0 : 1,
-1);
if (recurse && is_folder)
{
@@ -1509,7 +1530,7 @@ presets_list_append(signal_user_data_t *ud, const hb_preset_index_t *path)
2, def ? 2 : 0,
3, color,
4, description,
- 5, type == PRESETS_BUILTIN ? 0 : 1,
+ 5, type == HB_PRESET_TYPE_OFFICIAL ? 0 : 1,
-1);
if (is_folder)
{
@@ -1617,7 +1638,7 @@ ghb_settings_to_preset(GhbValue *settings)
gboolean autoscale, br, constant;
ghb_dict_set_bool(preset, "Default", 0);
- ghb_dict_set_int(preset, "Type", PRESETS_CUSTOM);
+ ghb_dict_set_int(preset, "Type", HB_PRESET_TYPE_CUSTOM);
if (!ghb_dict_get_bool(preset, "PictureWidthEnable"))
{
ghb_dict_remove(preset, "PictureWidth");
@@ -1818,94 +1839,78 @@ ghb_presets_load(signal_user_data_t *ud)
store_presets();
}
}
+ ghb_update_ui_combo_box(ud, "PresetCategory", NULL, FALSE);
}
static void
-settings_save(signal_user_data_t *ud, hb_preset_index_t *path, const char *name)
-{
- GhbValue *dict;
- gboolean replace = FALSE, def = FALSE;
-
- dict = hb_preset_get(path);
- if (dict != NULL)
- {
- gboolean is_folder;
- int type;
- const char *s;
-
- def = ghb_dict_get_bool(dict, "Default");
- is_folder = ghb_dict_get_bool(dict, "Folder");
- type = ghb_dict_get_int(dict, "Type");
- s = ghb_dict_get_string(dict, "PresetName");
- if (s == NULL || strcmp(s, name) || type != PRESETS_CUSTOM || is_folder)
+settings_save(signal_user_data_t *ud, const char * category,
+ const char *name, const char * desc)
+{
+ GhbValue * preset, * new_preset;
+ gboolean def = FALSE;
+ hb_preset_index_t * folder_path, * path;
+ char * fullname;
+
+ folder_path = hb_preset_search_index(category, 0, HB_PRESET_TYPE_CUSTOM);
+ if (folder_path->depth <= 0)
+ {
+ GhbValue * new_folder;
+ new_folder = ghb_dict_new();
+ ghb_dict_set_string(new_folder, "PresetName", category);
+ ghb_dict_set(new_folder, "ChildrenArray", ghb_array_new());
+ ghb_dict_set_int(new_folder, "Type", HB_PRESET_TYPE_CUSTOM);
+ ghb_dict_set_bool(new_folder, "Folder", TRUE);
+ int index = hb_preset_append(folder_path, new_folder);
+ if (index >= 0)
{
- // Name changed or original preset was builtin or original
- // was a folder. Don't replace it.
- replace = FALSE;
- path->depth--;
- if (type != PRESETS_CUSTOM)
- {
- // Don't put new custom presets in a builtin folder
- path->depth = 0;
- }
+ folder_path->index[folder_path->depth++] = index;
+ presets_list_append(ud, folder_path);
}
else
{
- replace = TRUE;
+ ghb_log("Failed to create category (%s)...", category);
+ return;
}
+ ghb_value_free(&new_folder);
}
- char * new_name = strdup(name);
- if (!replace)
- {
- // We are creating a new preset. Make sure there is not
- // another preset in this folder that has the same name
- int ii, count, index = 1;
- GhbValue *children;
- children = hb_presets_get_folder_children(path);
- count = ghb_array_len(children);
- do
- {
- for (ii = 0; ii < count; ii++)
- {
- GhbValue *preset;
- const char *s;
+ new_preset = ghb_settings_to_preset(ud->settings);
+ ghb_dict_set_string(new_preset, "PresetName", name);
+ ghb_dict_set_string(new_preset, "PresetDescription", desc);
- preset = ghb_array_get(children, ii);
- s = ghb_dict_get_string(preset, "PresetName");
- if (s != NULL && !strcmp(s, new_name))
- {
- free(new_name);
- new_name = g_strdup_printf("%s (%d)", name, index++);
- break;
- }
- }
- } while (ii < count);
- }
- dict = ghb_settings_to_preset(ud->settings);
- ghb_dict_set_string(dict, "PresetName", new_name);
- free(new_name);
- if (replace)
+ fullname = g_strdup_printf("/%s/%s", category, name);
+ path = hb_preset_search_index(fullname, 0, HB_PRESET_TYPE_CUSTOM);
+ preset = hb_preset_get(path);
+ if (preset != NULL)
{
+ // Replacing an existing preset
+ def = ghb_dict_get_bool(preset, "Default");
+
// If we are replacing the default preset, re-mark it as default
- ghb_dict_set_bool(dict, "Default", def);
+ ghb_dict_set_bool(new_preset, "Default", def);
// Already exists, update its description
- if (hb_preset_set(path, dict) >= 0)
+ if (hb_preset_set(path, new_preset) >= 0)
{
presets_list_update_item(ud, path, FALSE);
}
}
else
{
- // Append to the folder list the source came from
- int index = hb_preset_append(path, dict);
+ // Adding a new preset
+ // Append to the folder
+ int index = hb_preset_append(folder_path, new_preset);
if (index >= 0)
{
- path->index[path->depth++] = index;
- presets_list_append(ud, path);
+ folder_path->index[folder_path->depth++] = index;
+ presets_list_append(ud, folder_path);
}
+ *path = *folder_path;
}
- ghb_value_free(&dict);
+
+
+ free(fullname);
+ ghb_value_free(&new_preset);
+
store_presets();
ghb_presets_menu_reinit(ud);
@@ -1913,63 +1918,9 @@ settings_save(signal_user_data_t *ud, hb_preset_index_t *path, const char *name)
// Make the new preset the selected item
select_preset2(ud, path);
ud->dont_clear_presets = FALSE;
- return;
-}
-static void
-folder_save(signal_user_data_t *ud, hb_preset_index_t *path, const char *name)
-{
- GhbValue *dict;
-
- dict = hb_preset_get(path);
- if (dict != NULL)
- {
- gboolean is_folder;
- int type;
- const char *s;
-
- is_folder = ghb_dict_get_bool(dict, "Folder");
- type = ghb_dict_get_int(dict, "Type");
- s = ghb_dict_get_string(dict, "PresetName");
- if (s == NULL || strcmp(s, name) || type != PRESETS_CUSTOM || !is_folder)
- {
- // Name changed or original preset was builtin or original
- // was a not a folder. Don't replace it.
- dict = NULL;
- path->depth--;
- if (type != PRESETS_CUSTOM)
- {
- // Don't put new custom presets in a builtin folder
- path->depth = 1;
- }
- }
- }
- if (dict != NULL)
- {
- // Already exists, update its description
- dict = hb_preset_get(path);
- ghb_dict_set(dict, "PresetDescription",
- ghb_value_dup(ghb_dict_get(ud->settings, "PresetDescription")));
- presets_list_update_item(ud, path, FALSE);
- }
- else
- {
- dict = ghb_dict_new();
- ghb_dict_set(dict, "PresetDescription",
- ghb_value_dup(ghb_dict_get(ud->settings, "PresetDescription")));
- ghb_dict_set_string(dict, "PresetName", name);
- ghb_dict_set(dict, "ChildrenArray", ghb_array_new());
- ghb_dict_set_int(dict, "Type", PRESETS_CUSTOM);
- ghb_dict_set_bool(dict, "Folder", TRUE);
- int index = hb_preset_append(path, dict);
- if (index >= 0)
- {
- path->index[path->depth++] = index;
- presets_list_append(ud, path);
- }
- ghb_value_free(&dict);
- }
- store_presets();
+ free(folder_path);
+ free(path);
return;
}
@@ -2140,64 +2091,75 @@ preset_export_action_cb(GSimpleAction *action, GVariant *param,
}
G_MODULE_EXPORT void
-preset_folder_action_cb(GSimpleAction *action, GVariant *param,
- signal_user_data_t *ud)
-{
- GtkWidget *dialog;
- GtkEntry *entry;
- GtkTextView *desc;
- GtkResponseType response;
- hb_preset_index_t *path;
- const gchar *name;
- const gchar *description;
-
- path = get_selected_path(ud);
- name = ghb_dict_get_string(ud->settings, "PresetName");
- description = ghb_dict_get_string(ud->settings, "PresetDescription");
- ghb_ui_update(ud, "FolderDescription", ghb_string_value(description));
-
- desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "FolderDescription"));
- dialog = GHB_WIDGET(ud->builder, "preset_new_folder_dialog");
- entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "FolderName"));
- gtk_entry_set_text(entry, name);
- response = gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_hide(dialog);
- if (response == GTK_RESPONSE_OK)
- {
- // save the preset
- const gchar *name = gtk_entry_get_text(entry);
- GhbValue *val = ghb_widget_value(GTK_WIDGET(desc));
- ghb_dict_set(ud->settings, "PresetDescription", ghb_value_dup(val));
- folder_save(ud, path, name);
- }
- free(path);
-}
-
-G_MODULE_EXPORT void
preset_save_action_cb(GSimpleAction *action, GVariant *param,
signal_user_data_t *ud)
{
- const gchar *name;
- const gchar *fullname;
- hb_preset_index_t *path;
- int width, height;
- gboolean autoscale;
- GtkWidget *dialog;
- GtkEntry *entry;
- GtkTextView *desc;
- GtkResponseType response;
+ const char * category = NULL;
+ const gchar * name;
+ const gchar * fullname;
+ int type;
+ hb_preset_index_t * path;
+ int width, height;
+ gboolean autoscale;
+ GtkWidget * dialog;
+ GtkEntry * entry;
+ GtkTextView * tv;
+ GhbValue * dict;
+ GtkResponseType response;
name = ghb_dict_get_string(ud->settings, "PresetName");
+ type = ghb_dict_get_int(ud->settings, "Type");
fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
width = ghb_dict_get_int(ud->settings, "PictureWidth");
height = ghb_dict_get_int(ud->settings, "PictureHeight");
autoscale = ghb_dict_get_bool(ud->settings, "autoscale");
+
ghb_ui_update(ud, "PictureWidthEnable", ghb_boolean_value(!autoscale));
ghb_ui_update(ud, "PictureHeightEnable", ghb_boolean_value(!autoscale));
- path = hb_preset_search_index(fullname, 0);
- desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "PresetDescription"));
+ path = hb_preset_search_index(fullname, 0, type);
+
+ // Find an appropriate default category
+ if (path != NULL)
+ {
+ path->depth = 1;
+ dict = hb_preset_get(path);
+ if (ghb_dict_get_bool(dict, "Folder"))
+ {
+ category = ghb_dict_get_string(dict, "PresetName");
+ }
+ free(path);
+ }
+ if (category == NULL)
+ {
+ // Find first custom folder
+ hb_value_t * presets;
+ int ii, count;
+
+ presets = hb_presets_get();
+ count = hb_value_array_len(presets);
+ for (ii = 0; ii < count; ii++)
+ {
+ dict = hb_value_array_get(presets, ii);
+ if (!ghb_dict_get_bool(dict, "Folder"))
+ {
+ continue;
+ }
+ if (ghb_dict_get_int(dict, "Type") == 1)
+ {
+ category = ghb_dict_get_string(dict, "PresetName");
+ break;
+ }
+ }
+ }
+ if (category == NULL)
+ {
+ // Force creation of new category
+ category = "new";
+ }
+ ghb_ui_update(ud, "PresetCategory", ghb_string_value(category));
+ tv = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "PresetDescription"));
if (!width)
{
width = ghb_dict_get_int(ud->settings, "scale_width");
@@ -2216,18 +2178,65 @@ preset_save_action_cb(GSimpleAction *action, GVariant *param,
gtk_widget_hide(dialog);
if (response == GTK_RESPONSE_OK)
{
+ GtkTextBuffer * buffer;
+ GtkTextIter start, end;
+ char * desc;
+
// save the preset
name = gtk_entry_get_text(entry);
- ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc));
- settings_save(ud, path, name);
+ category = ghb_dict_get_string(ud->settings, "PresetCategory");
+ if (!strcmp(category, "new"))
+ {
+ entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "PresetCategoryEntry"));
+ category = gtk_entry_get_text(entry);
+ }
+ if (category == NULL || category[0] == 0)
+ {
+ ghb_log("Invalid empty category.");
+ return;
+ }
+ buffer = gtk_text_view_get_buffer(tv);
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ desc = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ settings_save(ud, category, name, desc);
+ free(desc);
}
- free(path);
+}
+
+static void
+preset_save_set_ok_sensitive(signal_user_data_t *ud)
+{
+ GtkEntry * entry;
+ GtkWidget * ok_button;
+ const char * name;
+ const char * category;
+ const char * category_name;
+ gboolean sensitive;
+
+ ok_button = GHB_WIDGET(ud->builder, "preset_ok");
+
+ category = ghb_dict_get_string(ud->settings, "PresetCategory");
+ entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "PresetName"));
+ name = gtk_entry_get_text(entry);
+ entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "PresetCategoryName"));
+ category_name = gtk_entry_get_text(entry);
+
+ sensitive = name[0] && (strcmp(category, "new") || category_name[0]);
+ gtk_widget_set_sensitive(ok_button, sensitive);
}
G_MODULE_EXPORT void
-preset_type_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+preset_category_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
ghb_widget_to_setting(ud->settings, widget);
+ preset_save_set_ok_sensitive(ud);
+ ghb_check_dependency(ud, widget, NULL);
+}
+
+G_MODULE_EXPORT void
+preset_name_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ preset_save_set_ok_sensitive(ud);
}
G_MODULE_EXPORT void
@@ -2247,16 +2256,17 @@ G_MODULE_EXPORT void
preset_remove_action_cb(GSimpleAction *action, GVariant *param,
signal_user_data_t *ud)
{
-
+ int type;
const char * fullname;
hb_preset_index_t * path;
- fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
+ type = ghb_dict_get_int(ud->settings, "Type");
+ fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
if (fullname == NULL)
{
return;
}
- path = hb_preset_search_index(fullname, 0);
+ path = hb_preset_search_index(fullname, 0, type);
if (path == NULL)
{
return;
@@ -2321,6 +2331,7 @@ preset_remove_action_cb(GSimpleAction *action, GVariant *param,
}
}
free(path);
+ ghb_update_ui_combo_box(ud, "PresetCategory", NULL, FALSE);
}
// controls where valid drop locations are
@@ -2380,7 +2391,7 @@ presets_drag_motion_cb(
return TRUE;
}
// Don't allow repositioning of builtin presets
- if (src_ptype != PRESETS_CUSTOM)
+ if (src_ptype != HB_PRESET_TYPE_CUSTOM)
{
gdk_drag_status(ctx, 0, time);
return TRUE;
@@ -2407,12 +2418,12 @@ presets_drag_motion_cb(
}
else
{
- dst_ptype = PRESETS_CUSTOM;
+ dst_ptype = HB_PRESET_TYPE_CUSTOM;
dst_folder = FALSE;
}
// Don't allow mixing custom presets in the builtins
- if (dst_ptype != PRESETS_CUSTOM)
+ if (dst_ptype != HB_PRESET_TYPE_CUSTOM)
{
gdk_drag_status(ctx, 0, time);
return TRUE;
@@ -2493,7 +2504,7 @@ presets_drag_cb(
src_folder = preset_is_folder(src_path);
// Don't allow repositioning of builtin presets
- if (src_ptype != PRESETS_CUSTOM)
+ if (src_ptype != HB_PRESET_TYPE_CUSTOM)
{
free(src_path);
return;
diff --git a/gtk/src/presets.h b/gtk/src/presets.h
index b71137375..cd14d48ce 100644
--- a/gtk/src/presets.h
+++ b/gtk/src/presets.h
@@ -42,7 +42,7 @@ gchar* ghb_get_user_config_dir(gchar *subdir);
void ghb_override_user_config_dir(char *dir);
void ghb_settings_to_ui(signal_user_data_t *ud, GhbValue *dict);
void ghb_clear_presets_selection(signal_user_data_t *ud);
-void ghb_select_preset(signal_user_data_t *ud, const char *name);
+void ghb_select_preset(signal_user_data_t *ud, const char *name, int type);
void ghb_select_default_preset(signal_user_data_t *ud);
void ghb_presets_list_init(signal_user_data_t *ud,
const hb_preset_index_t *path);
diff --git a/libhb/preset.c b/libhb/preset.c
index af94d8539..19a013211 100644
--- a/libhb/preset.c
+++ b/libhb/preset.c
@@ -73,17 +73,25 @@ typedef struct
{
preset_do_context_t do_ctx;
const char *name;
+ int type;
int recurse;
int last_match_idx;
} preset_search_context_t;
typedef int (*preset_do_f)(hb_value_t *preset, preset_do_context_t *ctx);
-static int preset_cmp_idx(hb_value_t *preset, int idx, const char *name)
+static int preset_cmp_idx(hb_value_t *preset, int idx,
+ const char *name, int type)
{
const char *next, *preset_name;
int ii, len;
+ if (type != HB_PRESET_TYPE_ALL &&
+ type != hb_value_get_int(hb_dict_get(preset, "Type")))
+ {
+ return PRESET_DO_NEXT;
+ }
+
// Strip leading '/'
if (name[0] == '/')
name++;
@@ -134,10 +142,10 @@ static int do_preset_search(hb_value_t *preset, preset_do_context_t *do_ctx)
idx -= ctx->last_match_idx;
}
- result = preset_cmp_idx(preset, idx, ctx->name);
+ result = preset_cmp_idx(preset, idx, ctx->name, ctx->type);
if (ctx->recurse && result == PRESET_DO_SKIP)
{
- result = preset_cmp_idx(preset, 0, ctx->name);
+ result = preset_cmp_idx(preset, 0, ctx->name, ctx->type);
ctx->last_match_idx = idx;
}
if (result == PRESET_DO_PARTIAL)
@@ -168,7 +176,7 @@ static int do_preset_clean(hb_value_t *preset, preset_do_context_t *do_ctx)
static int do_delete_builtin(hb_value_t *preset, preset_do_context_t *ctx)
{
- if (hb_value_get_int(hb_dict_get(preset, "Type")) == 0)
+ if (hb_value_get_int(hb_dict_get(preset, "Type")) == HB_PRESET_TYPE_OFFICIAL)
return PRESET_DO_DELETE;
return PRESET_DO_NEXT;
}
@@ -259,7 +267,7 @@ static int presets_do(preset_do_f do_func, hb_value_t *preset,
hb_preset_index_t* hb_preset_index_init(const int *index, int depth)
{
hb_preset_index_t *path;
- path = malloc(sizeof(hb_preset_index_t));
+ path = calloc(1, sizeof(hb_preset_index_t));
path->depth = depth;
if (index != NULL)
memcpy(path->index, index, depth * sizeof(int));
@@ -3209,13 +3217,15 @@ char * hb_presets_builtin_get_json(void)
// I assume that the actual preset name does not include any '/'
//
// A reference to the preset is returned
-static hb_preset_index_t * preset_lookup_path(const char *name, int recurse)
+static hb_preset_index_t * preset_lookup_path(const char *name,
+ int recurse, int type)
{
preset_search_context_t ctx;
int result;
ctx.do_ctx.path.depth = 1;
ctx.name = name;
+ ctx.type = type;
ctx.recurse = recurse;
ctx.last_match_idx = -1;
result = presets_do(do_preset_search, hb_presets,
@@ -3236,24 +3246,25 @@ static hb_preset_index_t * preset_lookup_path(const char *name, int recurse)
// I assume that the actual preset name does not include any '/'
//
// A copy of the preset is returned
-hb_preset_index_t * hb_preset_search_index(const char *name, int recurse)
+hb_preset_index_t * hb_preset_search_index(const char *name,
+ int recurse, int type)
{
- return preset_lookup_path(name, recurse);
+ return preset_lookup_path(name, recurse, type);
}
-hb_value_t * hb_preset_search(const char *name, int recurse)
+hb_value_t * hb_preset_search(const char *name, int recurse, int type)
{
- hb_preset_index_t *path = preset_lookup_path(name, recurse);
+ hb_preset_index_t *path = preset_lookup_path(name, recurse, type);
hb_value_t *preset = hb_preset_get(path);
free(path);
return preset;
}
-char * hb_preset_search_json(const char *name, int recurse)
+char * hb_preset_search_json(const char *name, int recurse, int type)
{
hb_value_t * preset;
char *json;
- preset = hb_preset_search(name, recurse);
+ preset = hb_preset_search(name, recurse, type);
if (preset == NULL)
return NULL;
json = hb_value_get_json(preset);
diff --git a/libhb/preset.h b/libhb/preset.h
index e797edeb6..61ffaf9b6 100644
--- a/libhb/preset.h
+++ b/libhb/preset.h
@@ -14,6 +14,10 @@
#define HB_MAX_PRESET_FOLDER_DEPTH 8
+#define HB_PRESET_TYPE_OFFICIAL 0
+#define HB_PRESET_TYPE_CUSTOM 1
+#define HB_PRESET_TYPE_ALL 2
+
typedef struct hb_preset_index_s hb_preset_index_t;
// A preset index is a list of indexes that specifies a path to a
@@ -160,9 +164,11 @@ void hb_sanitize_audio_settings(const hb_title_t * title,
// in the name will be performed.
//
// I assume that the actual preset name does not include any '/'
-hb_preset_index_t * hb_preset_search_index(const char *name, int recurse);
-hb_value_t * hb_preset_search(const char *name, int recurse);
-char * hb_preset_search_json(const char *name, int recurse);
+hb_preset_index_t * hb_preset_search_index(const char *name,
+ int recurse, int type);
+hb_value_t * hb_preset_search(const char *name, int recurse, int type);
+char * hb_preset_search_json(const char *name,
+ int recurs, int typee);
hb_value_t * hb_presets_get_folder_children(const hb_preset_index_t *path);
hb_value_t * hb_preset_get(const hb_preset_index_t *path);
diff --git a/test/test.c b/test/test.c
index e2336dab0..1e3238989 100644
--- a/test/test.c
+++ b/test/test.c
@@ -3260,7 +3260,8 @@ static hb_dict_t * PreparePreset(const char *preset_name)
if (preset_name != NULL)
{
- preset = hb_preset_search(preset_name, 1 /*recurse*/);
+ preset = hb_preset_search(preset_name, 1 /*recurse*/,
+ HB_PRESET_TYPE_ALL);
if (preset == NULL)
{
fprintf(stderr, "Invalid preset %s\n"