diff --git a/inc/widget_builder.h b/inc/widget_builder.h index 60c0857..883a7ed 100644 --- a/inc/widget_builder.h +++ b/inc/widget_builder.h @@ -29,6 +29,4 @@ struct widget_builder { size_t actions; }; -void wofi_free_widget_builder(struct widget_builder* builder); - #endif diff --git a/inc/widget_builder_api.h b/inc/widget_builder_api.h index d839c3e..75883d4 100644 --- a/inc/widget_builder_api.h +++ b/inc/widget_builder_api.h @@ -30,7 +30,7 @@ void wofi_widget_builder_set_search_text(struct widget_builder* builder, char* s void wofi_widget_builder_set_action(struct widget_builder* builder, char* action); -void wofi_widget_builder_insert_text(struct widget_builder* builder, char* text, char* css_name); +void wofi_widget_builder_insert_text(struct widget_builder* builder, const char* text, char* css_name); void wofi_widget_builder_insert_image(struct widget_builder* builder, GdkPixbuf* pixbuf, char* css_name); @@ -38,4 +38,6 @@ struct widget_builder* wofi_widget_builder_get_idx(struct widget_builder* builde struct widget* wofi_widget_builder_get_widget(struct widget_builder* builder); +void wofi_free_widget_builder(struct widget_builder* builder); + #endif diff --git a/man/wofi-widget-builder.3 b/man/wofi-widget-builder.3 index 3b8bc41..6ae686e 100644 --- a/man/wofi-widget-builder.3 +++ b/man/wofi-widget-builder.3 @@ -77,3 +77,10 @@ Constructs a new widget from the specified builder, the widget can be returned b .B struct widget_builder* builder \- The builder to construct a widget for + +.TP +.B void wofi_free_widget_builder(struct widget_builder* builder) +Frees the specified builder + +.B struct widget_builder* builder +\- The builder to free diff --git a/modes/drun.c b/modes/drun.c index d6cda41..217d5d9 100644 --- a/modes/drun.c +++ b/modes/drun.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -43,58 +43,6 @@ static struct wl_list desktop_entries; static bool print_command; static bool display_generic; -static char* get_text(char* file, char* action) { - GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file); - if(info == NULL || g_desktop_app_info_get_is_hidden(info) || g_desktop_app_info_get_nodisplay(info)) { - return NULL; - } - const char* name; - char* generic_name = strdup(""); - if(action == NULL) { - name = g_app_info_get_display_name(G_APP_INFO(info)); - if(display_generic) { - const char* gname = g_desktop_app_info_get_generic_name(info); - if(gname != NULL) { - free(generic_name); - generic_name = utils_concat(3, " (", gname, ")"); - } - } - } else { - name = g_desktop_app_info_get_action_name(info, action); - } - if(name == NULL) { - return NULL; - } - if(wofi_allow_images()) { - GIcon* icon = g_app_info_get_icon(G_APP_INFO(info)); - if(G_IS_FILE_ICON(icon)) { - GFile* file = g_file_icon_get_file(G_FILE_ICON(icon)); - char* path = g_file_get_path(file); - char* ret = utils_concat(5, "img:", path, ":text:", name, generic_name); - free(generic_name); - return ret; - } else { - GtkIconTheme* theme = gtk_icon_theme_get_default(); - GtkIconInfo* info = NULL; - if(icon != NULL) { - const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON(icon)); - info = gtk_icon_theme_choose_icon(theme, (const gchar**) icon_names, wofi_get_image_size(), 0); - } - if(info == NULL) { - info = gtk_icon_theme_lookup_icon(theme, "application-x-executable", wofi_get_image_size(), 0); - } - const gchar* icon_path = gtk_icon_info_get_filename(info); - char* ret = utils_concat(5, "img:", icon_path, ":text:", name, generic_name); - free(generic_name); - return ret; - } - } else { - char* ret = utils_concat(2, name, generic_name); - free(generic_name); - return ret; - } -} - static char* get_search_text(char* file) { GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file); const char* name = g_app_info_get_display_name(G_APP_INFO(info)); @@ -124,6 +72,91 @@ static char* get_search_text(char* file) { return ret; } +static bool populate_widget(char* file, char* action, struct widget_builder* builder) { + GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file); + if(info == NULL || g_desktop_app_info_get_is_hidden(info) || g_desktop_app_info_get_nodisplay(info)) { + return false; + } + const char* name; + char* generic_name = strdup(""); + if(action == NULL) { + name = g_app_info_get_display_name(G_APP_INFO(info)); + if(display_generic) { + const char* gname = g_desktop_app_info_get_generic_name(info); + if(gname != NULL) { + free(generic_name); + generic_name = utils_concat(3, " (", gname, ")"); + } + } + } else { + name = g_desktop_app_info_get_action_name(info, action); + } + if(name == NULL) { + free(generic_name); + return false; + } + + + + if(wofi_allow_images()) { + GIcon* icon = g_app_info_get_icon(G_APP_INFO(info)); + GdkPixbuf* pixbuf; + if(G_IS_FILE_ICON(icon)) { + GFile* file = g_file_icon_get_file(G_FILE_ICON(icon)); + char* path = g_file_get_path(file); + pixbuf = gdk_pixbuf_new_from_file(path, NULL); + } else { + GtkIconTheme* theme = gtk_icon_theme_get_default(); + GtkIconInfo* info = NULL; + if(icon != NULL) { + const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON(icon)); + info = gtk_icon_theme_choose_icon(theme, (const gchar**) icon_names, wofi_get_image_size(), 0); + } + if(info == NULL) { + info = gtk_icon_theme_lookup_icon(theme, "application-x-executable", wofi_get_image_size(), 0); + } + pixbuf = gtk_icon_info_load_icon(info, NULL); + } + + int width = gdk_pixbuf_get_width(pixbuf); + int height = gdk_pixbuf_get_height(pixbuf); + uint64_t image_size = wofi_get_image_size(); + + if(height > width) { + float percent = (float) image_size / height; + GdkPixbuf* tmp = gdk_pixbuf_scale_simple(pixbuf, width * percent, image_size, GDK_INTERP_BILINEAR); + g_object_unref(pixbuf); + pixbuf = tmp; + } else { + float percent = (float) image_size / width; + GdkPixbuf* tmp = gdk_pixbuf_scale_simple(pixbuf, image_size, height * percent, GDK_INTERP_BILINEAR); + g_object_unref(pixbuf); + pixbuf = tmp; + } + + wofi_widget_builder_insert_image(builder, pixbuf, "icon"); + g_object_unref(pixbuf); + } + wofi_widget_builder_insert_text(builder, name, "name"); + wofi_widget_builder_insert_text(builder, generic_name, "generic-name"); + free(generic_name); + + if(action == NULL) { + wofi_widget_builder_set_action(builder, file); + } else { + char* action_txt = utils_concat(3, file, " ", action); + wofi_widget_builder_set_action(builder, action_txt); + free(action_txt); + } + + + char* search_txt = get_search_text(file); + wofi_widget_builder_set_search_text(builder, search_txt); + free(search_txt); + + return true; +} + static const gchar* const* get_actions(char* file, size_t* action_count) { *action_count = 0; GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file); @@ -140,44 +173,22 @@ static const gchar* const* get_actions(char* file, size_t* action_count) { return actions; } -static char** get_action_text(char* file, size_t* text_count) { - *text_count = 0; - - char* tmp = get_text(file, NULL); - if(tmp == NULL) { - return NULL; - } - +static struct widget_builder* populate_actions(char* file, size_t* text_count) { const gchar* const* action_names = get_actions(file, text_count); ++*text_count; - char** text = malloc(*text_count * sizeof(char*)); - text[0] = tmp; - for(size_t count = 1; count < *text_count; ++count) { - text[count] = get_text(file, (gchar*) action_names[count - 1]); - } - return text; -} -static char** get_action_actions(char* file, size_t* action_count) { - *action_count = 0; - - char* tmp = strdup(file); - if(tmp == NULL) { + struct widget_builder* builder = wofi_create_widget_builder(mode, *text_count); + if(!populate_widget(file, NULL, builder)) { + wofi_free_widget_builder(builder); return NULL; } - const gchar* const* action_names = get_actions(file, action_count); - - ++*action_count; - char** actions = malloc(*action_count * sizeof(char*)); - actions[0] = tmp; - - for(size_t count = 1; count < *action_count; ++count) { - actions[count] = utils_concat(3, file, " ", (gchar*) action_names[count - 1]); + for(size_t count = 1; count < *text_count; ++count) { + populate_widget(file, (gchar*) action_names[count - 1], wofi_widget_builder_get_idx(builder, count)); } - return actions; + return builder; } static char* get_id(char* path) { @@ -201,32 +212,22 @@ static struct widget* create_widget(char* full_path) { return NULL; } - size_t action_count; - char** text = get_action_text(full_path, &action_count); map_put(entries, id, "true"); - if(text == NULL) { + + size_t action_count; + + struct widget_builder* builder = populate_actions(full_path, &action_count); + if(builder == NULL) { wofi_remove_cache(mode, full_path); free(id); free(full_path); return NULL; } - char** actions = get_action_actions(full_path, &action_count); - - char* search_text = get_search_text(full_path); - - struct widget* ret = wofi_create_widget(mode, text, search_text, actions, action_count); - - for(size_t count = 0; count < action_count; ++count) { - free(actions[count]); - free(text[count]); - } + struct widget* ret = wofi_widget_builder_get_widget(builder); free(id); - free(text); - free(actions); free(full_path); - free(search_text); return ret; } diff --git a/src/widget_builder.c b/src/widget_builder.c index d7c572f..1cd1e1d 100644 --- a/src/widget_builder.c +++ b/src/widget_builder.c @@ -42,7 +42,7 @@ void wofi_widget_builder_set_action(struct widget_builder* builder, char* action wofi_property_box_add_property(builder->box, "action", action); } -void wofi_widget_builder_insert_text(struct widget_builder* builder, char* text, char* css_name) { +void wofi_widget_builder_insert_text(struct widget_builder* builder, const char* text, char* css_name) { GtkWidget* label = gtk_label_new(text); gtk_container_add(GTK_CONTAINER(builder->box), label); if(css_name != NULL) { diff --git a/src/wofi.c b/src/wofi.c index 3cbe716..f02488d 100644 --- a/src/wofi.c +++ b/src/wofi.c @@ -356,16 +356,24 @@ char* wofi_parse_image_escapes(const char* text) { return parse_images(NULL, text, false); } -static GtkWidget* create_label(char* mode, char* text, char* search_text, char* action) { - GtkWidget* box = wofi_property_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_set_name(box, "unselected"); - GtkStyleContext* style = gtk_widget_get_style_context(box); - gtk_style_context_add_class(style, "entry"); - wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "mode", mode); - wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "action", action); +static void setup_label(char* mode, WofiPropertyBox* box) { + wofi_property_box_add_property(box, "mode", mode); char index[11]; snprintf(index, sizeof(index), "%u", ++widget_count); - wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "index", index); + wofi_property_box_add_property(box, "index", index); + + gtk_widget_set_name(GTK_WIDGET(box), "unselected"); + + GtkStyleContext* style = gtk_widget_get_style_context(GTK_WIDGET(box)); + gtk_style_context_add_class(style, "entry"); +} + +static GtkWidget* create_label(char* mode, char* text, char* search_text, char* action) { + GtkWidget* box = wofi_property_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + + wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "action", action); + + setup_label(mode, WOFI_PROPERTY_BOX(box)); if(allow_images) { parse_images(WOFI_PROPERTY_BOX(box), text, true); @@ -502,6 +510,7 @@ static gboolean _insert_widget(gpointer data) { box = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); } else { box = GTK_WIDGET(node->builder->box); + setup_label(node->builder->mode->name, WOFI_PROPERTY_BOX(box)); } gtk_expander_set_label_widget(GTK_EXPANDER(parent), box); @@ -514,6 +523,7 @@ static gboolean _insert_widget(gpointer data) { box = create_label(node->mode, node->text[count], node->search_text, node->actions[count]); } else { box = GTK_WIDGET(node->builder[count].box); + setup_label(node->builder->mode->name, WOFI_PROPERTY_BOX(box)); } GtkWidget* row = gtk_list_box_row_new(); @@ -527,6 +537,7 @@ static gboolean _insert_widget(gpointer data) { parent = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); } else { parent = GTK_WIDGET(node->builder->box); + setup_label(node->builder->mode->name, WOFI_PROPERTY_BOX(parent)); } }