From e3c79c3bd42e4d0da5fa50568a794c231f006999 Mon Sep 17 00:00:00 2001 From: Scoopta Date: Tue, 27 Aug 2019 23:15:18 -0700 Subject: [PATCH] Added support for inline images, this currently only works in dmenu mode --- Debug/src/subdir.mk | 6 +- Release/src/subdir.mk | 6 +- inc/{property_label.h => property_box.h} | 14 ++-- inc/wofi.h | 2 +- src/main.c | 16 +++- src/property_box.c | 58 ++++++++++++++ src/property_label.c | 52 ------------- src/wofi.c | 99 ++++++++++++++++++------ 8 files changed, 164 insertions(+), 89 deletions(-) rename inc/{property_label.h => property_box.h} (62%) create mode 100644 src/property_box.c delete mode 100644 src/property_label.c diff --git a/Debug/src/subdir.mk b/Debug/src/subdir.mk index 4be839f..da59fb6 100644 --- a/Debug/src/subdir.mk +++ b/Debug/src/subdir.mk @@ -7,7 +7,7 @@ C_SRCS += \ ../src/config.c \ ../src/main.c \ ../src/map.c \ -../src/property_label.c \ +../src/property_box.c \ ../src/utils.c \ ../src/wofi.c @@ -15,7 +15,7 @@ OBJS += \ ./src/config.o \ ./src/main.o \ ./src/map.o \ -./src/property_label.o \ +./src/property_box.o \ ./src/utils.o \ ./src/wofi.o @@ -23,7 +23,7 @@ C_DEPS += \ ./src/config.d \ ./src/main.d \ ./src/map.d \ -./src/property_label.d \ +./src/property_box.d \ ./src/utils.d \ ./src/wofi.d diff --git a/Release/src/subdir.mk b/Release/src/subdir.mk index ccec8f9..8ef99a5 100644 --- a/Release/src/subdir.mk +++ b/Release/src/subdir.mk @@ -7,7 +7,7 @@ C_SRCS += \ ../src/config.c \ ../src/main.c \ ../src/map.c \ -../src/property_label.c \ +../src/property_box.c \ ../src/utils.c \ ../src/wofi.c @@ -15,7 +15,7 @@ OBJS += \ ./src/config.o \ ./src/main.o \ ./src/map.o \ -./src/property_label.o \ +./src/property_box.o \ ./src/utils.o \ ./src/wofi.o @@ -23,7 +23,7 @@ C_DEPS += \ ./src/config.d \ ./src/main.d \ ./src/map.d \ -./src/property_label.d \ +./src/property_box.d \ ./src/utils.d \ ./src/wofi.d diff --git a/inc/property_label.h b/inc/property_box.h similarity index 62% rename from inc/property_label.h rename to inc/property_box.h index c8c3f61..1b44afe 100644 --- a/inc/property_label.h +++ b/inc/property_box.h @@ -15,19 +15,19 @@ along with Wofi. If not, see . */ -#ifndef PROPERTY_LABEL_H -#define PROPERTY_LABEL_H +#ifndef PROPERTY_BOX_H +#define PROPERTY_BOX_H #include #include -#define WOFI_TYPE_PROPERTY_LABEL wofi_property_label_get_type() -G_DECLARE_FINAL_TYPE(WofiPropertyLabel, wofi_property_label, WOFI, PROPERTY_LABEL, GtkLabel); +#define WOFI_TYPE_PROPERTY_BOX wofi_property_box_get_type() +G_DECLARE_FINAL_TYPE(WofiPropertyBox, wofi_property_box, WOFI, PROPERTY_BOX, GtkBox); -GtkWidget* wofi_property_label_new(const gchar* str); +GtkWidget* wofi_property_box_new(GtkOrientation orientation, gint spacing); -void wofi_property_label_add_property(WofiPropertyLabel* this, const gchar* key, gchar* value); +void wofi_property_box_add_property(WofiPropertyBox* this, const gchar* key, gchar* value); -const gchar* wofi_property_label_get_property(WofiPropertyLabel* this, const gchar* key); +const gchar* wofi_property_box_get_property(WofiPropertyBox* this, const gchar* key); #endif diff --git a/inc/wofi.h b/inc/wofi.h index 602e4b4..a21c0ce 100644 --- a/inc/wofi.h +++ b/inc/wofi.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/src/main.c b/src/main.c index 473cb0e..39552ca 100644 --- a/src/main.c +++ b/src/main.c @@ -61,6 +61,7 @@ static void print_usage(char** argv) { printf("--xoffset\t-x\tThe x offset\n"); printf("--yoffset\t-y\tThe y offset\n"); printf("--normal-window\t-n\tRender to a normal window\n"); + printf("--allow-images\t-i\tAllows images to be rendered\n"); exit(0); } @@ -242,6 +243,12 @@ int main(int argc, char** argv) { .flag = NULL, .val = 'n' }, + { + .name = "allow-images", + .has_arg = no_argument, + .flag = NULL, + .val = 'i' + }, { .name = NULL, .has_arg = 0, @@ -260,8 +267,9 @@ int main(int argc, char** argv) { char* x = NULL; char* y = NULL; char* normal_window = NULL; + char* allow_images = NULL; char opt; - while((opt = getopt_long(argc, argv, "hfc:s:C:dS:W:H:p:x:y:n", opts, NULL)) != -1) { + while((opt = getopt_long(argc, argv, "hfc:s:C:dS:W:H:p:x:y:ni", opts, NULL)) != -1) { switch(opt) { case 'h': print_usage(argv); @@ -307,6 +315,9 @@ int main(int argc, char** argv) { case 'n': normal_window = "true"; break; + case 'i': + allow_images = "true"; + break; } } @@ -400,6 +411,9 @@ int main(int argc, char** argv) { if(normal_window != NULL) { map_put(config, "normal_window", normal_window); } + if(allow_images != NULL) { + map_put(config, "allow_images", allow_images); + } gtk_init(&argc, &argv); diff --git a/src/property_box.c b/src/property_box.c new file mode 100644 index 0000000..b49dbe1 --- /dev/null +++ b/src/property_box.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 Scoopta + * This file is part of Wofi + * Wofi is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Wofi is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Wofi. If not, see . + */ + +#include + +struct _WofiPropertyBox { + GtkBox super; +}; + +typedef struct { + struct map* properties; +} WofiPropertyBoxPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(WofiPropertyBox, wofi_property_box, GTK_TYPE_BOX); + +static void wofi_property_box_init(WofiPropertyBox* box) { + WofiPropertyBoxPrivate* this = wofi_property_box_get_instance_private(box); + this->properties = map_init(); +} + +static void finalize(GObject* obj) { + WofiPropertyBoxPrivate* this = wofi_property_box_get_instance_private(WOFI_PROPERTY_BOX(obj)); + map_free(this->properties); + G_OBJECT_CLASS(wofi_property_box_parent_class)->finalize(obj); +} + +static void wofi_property_box_class_init(WofiPropertyBoxClass* class) { + GObjectClass* g_class = G_OBJECT_CLASS(class); + g_class->finalize = finalize; +} + +GtkWidget* wofi_property_box_new(GtkOrientation orientation, gint spacing) { + return g_object_new(WOFI_TYPE_PROPERTY_BOX, "orientation", orientation, "spacing", spacing, NULL); +} + +void wofi_property_box_add_property(WofiPropertyBox* box, const gchar* key, gchar* value) { + WofiPropertyBoxPrivate* this = wofi_property_box_get_instance_private(box); + map_put(this->properties, key, value); +} + +const gchar* wofi_property_box_get_property(WofiPropertyBox* box, const gchar* key) { + WofiPropertyBoxPrivate* this = wofi_property_box_get_instance_private(box); + return map_get(this->properties, key); +} diff --git a/src/property_label.c b/src/property_label.c deleted file mode 100644 index 6e3bee4..0000000 --- a/src/property_label.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2019 Scoopta - * This file is part of Wofi - * Wofi is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Wofi is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Wofi. If not, see . - */ - -#include - -struct _WofiPropertyLabel { - GtkLabel super; - struct map* properties; -}; - -G_DEFINE_TYPE(WofiPropertyLabel, wofi_property_label, GTK_TYPE_LABEL); - -static void wofi_property_label_init(WofiPropertyLabel* this) { - this->properties = map_init(); -} - -static void finalize(GObject* obj) { - WofiPropertyLabel* this = WOFI_PROPERTY_LABEL(obj); - map_free(this->properties); - G_OBJECT_CLASS(wofi_property_label_parent_class)->finalize(obj); -} - -static void wofi_property_label_class_init(WofiPropertyLabelClass* class) { - GObjectClass* g_class = G_OBJECT_CLASS(class); - g_class->finalize = finalize; -} - -GtkWidget* wofi_property_label_new(const gchar* str) { - return g_object_new(WOFI_TYPE_PROPERTY_LABEL, "label", str, NULL); -} - -void wofi_property_label_add_property(WofiPropertyLabel* this, const gchar* key, gchar* value) { - map_put(this->properties, key, value); -} - -const gchar* wofi_property_label_get_property(WofiPropertyLabel* this, const gchar* key) { - return map_get(this->properties, key); -} diff --git a/src/wofi.c b/src/wofi.c index c9a608e..c52ba12 100644 --- a/src/wofi.c +++ b/src/wofi.c @@ -25,6 +25,7 @@ static const gchar* filter; static char* mode; static time_t filter_time; static int64_t filter_rate; +static bool allow_images; struct node { char* text, *action; @@ -73,19 +74,72 @@ static void get_search(GtkSearchEntry* entry, gpointer data) { gtk_list_box_invalidate_filter(GTK_LIST_BOX(inner_box)); } -static GtkWidget* create_label(const char* text, char* action) { - GtkWidget* label = wofi_property_label_new(text); - gtk_widget_set_name(label, "unselected"); - wofi_property_label_add_property(WOFI_PROPERTY_LABEL(label), "action", action); - gtk_label_set_xalign(GTK_LABEL(label), 0); - return label; +static GtkWidget* create_label(char* text, char* action) { + GtkWidget* box = wofi_property_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(box, "unselected"); + wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "action", action); + if(allow_images) { + char* tmp = strdup(text); + char* original = tmp; + char* mode = NULL; + char* filter = NULL; + + size_t colon_count = utils_split(tmp, ':'); + for(size_t count = 0; count < colon_count; ++count) { + if(mode == NULL) { + mode = tmp; + } else { + if(strcmp(mode, "img") == 0) { + GdkPixbuf* buf = gdk_pixbuf_new_from_file(tmp, NULL); + int width = gdk_pixbuf_get_width(buf); + int height = gdk_pixbuf_get_height(buf); + if(height > width) { + float percent = 32.f / height; + GdkPixbuf* tmp = gdk_pixbuf_scale_simple(buf, width * percent, 32, GDK_INTERP_BILINEAR); + g_object_unref(buf); + buf = tmp; + } else { + float percent = 32.f / width; + GdkPixbuf* tmp = gdk_pixbuf_scale_simple(buf, 32, height * percent, GDK_INTERP_BILINEAR); + g_object_unref(buf); + buf = tmp; + } + GtkWidget* img = gtk_image_new_from_pixbuf(buf); + gtk_container_add(GTK_CONTAINER(box), img); + } else if(strcmp(mode, "text") == 0) { + if(filter == NULL) { + filter = strdup(tmp); + } else { + char* tmp_filter = utils_concat(2, filter, tmp); + free(filter); + filter = tmp_filter; + } + GtkWidget* label = gtk_label_new(tmp); + gtk_label_set_xalign(GTK_LABEL(label), 0); + gtk_container_add(GTK_CONTAINER(box), label); + } + mode = NULL; + } + tmp += strlen(tmp) + 1; + } + wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "filter", filter); + free(filter); + free(original); + } else { + wofi_property_box_add_property(WOFI_PROPERTY_BOX(box), "filter", text); + GtkWidget* label = gtk_label_new(text); + gtk_label_set_xalign(GTK_LABEL(label), 0); + gtk_container_add(GTK_CONTAINER(box), label); + } + + return box; } static gboolean insert_widget(gpointer data) { struct node* node = data; - GtkWidget* label = create_label(node->text, node->action); - gtk_container_add(node->container, label); - gtk_widget_show(label); + GtkWidget* box = create_label(node->text, node->action); + gtk_container_add(node->container, box); + gtk_widget_show_all(box); free(node->text); free(node->action); free(node); @@ -342,22 +396,22 @@ static void execute_action(char* mode, const gchar* cmd) { } } -static void activate_item(GtkListBox* box, GtkListBoxRow* row, gpointer data) { - (void) box; +static void activate_item(GtkListBox* list_box, GtkListBoxRow* row, gpointer data) { + (void) list_box; (void) data; - GtkWidget* label = gtk_bin_get_child(GTK_BIN(row)); - execute_action(mode, wofi_property_label_get_property(WOFI_PROPERTY_LABEL(label), "action")); + GtkWidget* box = gtk_bin_get_child(GTK_BIN(row)); + execute_action(mode, wofi_property_box_get_property(WOFI_PROPERTY_BOX(box), "action")); } -static void select_item(GtkListBox* box, GtkListBoxRow* row, gpointer data) { - (void) box; +static void select_item(GtkListBox* list_box, GtkListBoxRow* row, gpointer data) { + (void) list_box; (void) data; if(previous_selection != NULL) { gtk_widget_set_name(previous_selection, "unselected"); } - GtkWidget* label = gtk_bin_get_child(GTK_BIN(row)); - gtk_widget_set_name(label, "selected"); - previous_selection = label; + GtkWidget* box = gtk_bin_get_child(GTK_BIN(row)); + gtk_widget_set_name(box, "selected"); + previous_selection = box; } static void activate_search(GtkEntry* entry, gpointer data) { @@ -366,15 +420,15 @@ static void activate_search(GtkEntry* entry, gpointer data) { execute_action(mode, gtk_entry_get_text(entry)); } else { GtkListBoxRow* row = gtk_list_box_get_row_at_y(GTK_LIST_BOX(inner_box), 0); - GtkWidget* label = gtk_bin_get_child(GTK_BIN(row)); - execute_action(mode, wofi_property_label_get_property(WOFI_PROPERTY_LABEL(label), "action")); + GtkWidget* box = gtk_bin_get_child(GTK_BIN(row)); + execute_action(mode, wofi_property_box_get_property(WOFI_PROPERTY_BOX(box), "action")); } } static gboolean do_filter(GtkListBoxRow* row, gpointer data) { (void) data; - GtkWidget* label = gtk_bin_get_child(GTK_BIN(row)); - const gchar* text = gtk_label_get_text(GTK_LABEL(label)); + GtkWidget* box = gtk_bin_get_child(GTK_BIN(row)); + const gchar* text = wofi_property_box_get_property(WOFI_PROPERTY_BOX(box), "filter"); if(filter == NULL || strcmp(filter, "") == 0) { return TRUE; } @@ -419,6 +473,7 @@ void wofi_init(struct map* config) { char* prompt = config_get(config, "prompt", mode); filter_rate = strtol(config_get(config, "filter_rate", "100"), NULL, 10); filter_time = utils_get_time_millis(); + allow_images = strcmp(config_get(config, "allow_images", "false"), "true") == 0; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_realize(window);