Fix #1248: Crash when hiding file list
[geeqie.git] / src / search-and-run.cc
index 52a6b8b..c23da61 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <gdk/gdkkeysyms.h>
-
-#include "main.h"
 #include "search-and-run.h"
 
-#include "layout-util.h"
-#include "ui-misc.h"
-#include "window.h"
+#include <cstddef>
+
+#include <gdk/gdk.h>
+#include <glib-object.h>
+#include <glib.h>
+#include <pango/pango.h>
+
+#include "compat.h"
+#include "debug.h"
+#include "layout.h"
+#include "main-defines.h"
 
 enum {
        SAR_LABEL,
@@ -33,36 +38,34 @@ enum {
        SAR_COUNT
 };
 
-typedef struct _SarData SarData;
-struct _SarData
+struct SarData
 {
        GtkWidget *window;
-       GtkWidget *vbox;
-       GtkWidget *entry_box;
-       GtkEntryCompletion *completion;
        GtkListStore *command_store;
        GtkAction *action;
        LayoutWindow *lw;
        gboolean match_found;
+       GtkBuilder *builder;
 };
 
-static gint sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer UNUSED(data))
+static gint sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer)
 {
        gint ret = 0;
-       gchar *label1, *label2;
+       gchar *label1;
+       gchar *label2;
 
        gtk_tree_model_get(model, a, SAR_LABEL, &label1, -1);
        gtk_tree_model_get(model, b, SAR_LABEL, &label2, -1);
 
-       if (label1 == NULL || label2 == NULL)
+       if (label1 == nullptr || label2 == nullptr)
                {
-               if (label1 == NULL && label2 == NULL)
+               if (label1 == nullptr && label2 == nullptr)
                        {
                        ret = 0;
                        }
                else
                        {
-                       ret = (label1 == NULL) ? -1 : 1;
+                       ret = (label1 == nullptr) ? -1 : 1;
                        }
                }
        else
@@ -78,24 +81,26 @@ static gint sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTree
 
 static void command_store_populate(SarData* sar)
 {
-       GList *groups, *actions;
+       GList *groups;
+       GList *actions;
        GtkAction *action;
        const gchar *accel_path;
        GtkAccelKey key;
        GtkTreeIter iter;
        GtkTreeSortable *sortable;
-       gchar *label, *tooltip;
-       gchar *label2, *tooltip2;
+       gchar *label;
+       gchar *tooltip;
+       gchar *label2;
+       gchar *tooltip2;
        GString *new_command;
        gchar *existing_command;
        gboolean iter_found;
        gboolean duplicate_command;
        gchar *accel;
 
-       sar->command_store = gtk_list_store_new(SAR_COUNT, G_TYPE_STRING, G_TYPE_OBJECT);
-
+       sar->command_store = GTK_LIST_STORE(gtk_builder_get_object(sar->builder, "command_store"));
        sortable = GTK_TREE_SORTABLE(sar->command_store);
-       gtk_tree_sortable_set_sort_func(sortable, SAR_LABEL, sort_iter_compare_func, NULL, NULL);
+       gtk_tree_sortable_set_sort_func(sortable, SAR_LABEL, sort_iter_compare_func, nullptr, nullptr);
 
        gtk_tree_sortable_set_sort_column_id(sortable, SAR_LABEL, GTK_SORT_ASCENDING);
 
@@ -113,23 +118,23 @@ static void command_store_populate(SarData* sar)
                                accel = gtk_accelerator_get_label(key.accel_key, key.accel_mods);
 
                                /* menu items with no tooltip are placeholders */
-                               if (g_strrstr(accel_path, ".desktop") != NULL || tooltip != NULL)
+                               if (g_strrstr(accel_path, ".desktop") != nullptr || tooltip != nullptr)
                                        {
-                                       if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
+                                       if (pango_parse_markup(label, -1, '_', nullptr, &label2, nullptr, nullptr) && label2)
                                                {
                                                g_free(label);
                                                label = label2;
                                                }
                                        if (tooltip)
                                                {
-                                               if (pango_parse_markup(tooltip, -1, '_', NULL, &tooltip2, NULL, NULL) && label2)
+                                               if (pango_parse_markup(tooltip, -1, '_', nullptr, &tooltip2, nullptr, nullptr) && label2)
                                                        {
                                                        g_free(tooltip);
                                                        tooltip = tooltip2;
                                                        }
                                                }
 
-                                       new_command = g_string_new(NULL);
+                                       new_command = g_string_new(nullptr);
                                        if (g_strcmp0(label, tooltip) == 0)
                                                {
                                                g_string_append_printf(new_command, "%s : %s",label, accel);
@@ -177,17 +182,20 @@ static void command_store_populate(SarData* sar)
 
 static gboolean search_and_run_destroy(gpointer data)
 {
-       SarData *sar = data;
+       auto sar = static_cast<SarData *>(data);
 
-       sar->lw->sar_window = NULL;
-       gtk_widget_destroy(sar->window);
+       sar->lw->sar_window = nullptr;
+       g_object_unref(gtk_builder_get_object(sar->builder, "completion"));
+       g_object_unref(gtk_builder_get_object(sar->builder, "command_store"));
+       gq_gtk_widget_destroy(sar->window);
+       g_free(sar);
 
-       return TRUE;
+       return G_SOURCE_REMOVE;
 }
 
-static gboolean entry_box_activate_cb(GtkWidget *UNUSED(widget), gpointer data)
+static gboolean entry_box_activate_cb(GtkWidget *, gpointer data)
 {
-       SarData *sar = data;
+       auto sar = static_cast<SarData *>(data);
 
        if (sar->action)
                {
@@ -199,9 +207,9 @@ static gboolean entry_box_activate_cb(GtkWidget *UNUSED(widget), gpointer data)
        return TRUE;
 }
 
-static gboolean keypress_cb(GtkWidget *UNUSED(widget), GdkEventKey *event, gpointer data)
+static gboolean keypress_cb(GtkWidget *, GdkEventKey *event, gpointer data)
 {
-       SarData *sar = data;
+       auto sar = static_cast<SarData *>(data);
        gboolean ret = FALSE;
 
        switch (event->keyval)
@@ -214,15 +222,15 @@ static gboolean keypress_cb(GtkWidget *UNUSED(widget), GdkEventKey *event, gpoin
                        break;
                default:
                        sar->match_found = FALSE;
-                       sar->action = NULL;
+                       sar->action = nullptr;
                }
 
        return ret;
 }
 
-static gboolean match_selected_cb(GtkEntryCompletion *UNUSED(widget), GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+static gboolean match_selected_cb(GtkEntryCompletion *, GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
 {
-       SarData *sar = data;
+       auto sar = static_cast<SarData *>(data);
 
        gtk_tree_model_get(GTK_TREE_MODEL(model), iter, SAR_ACTION, &sar->action, -1);
 
@@ -231,14 +239,14 @@ static gboolean match_selected_cb(GtkEntryCompletion *UNUSED(widget), GtkTreeMod
                gtk_action_activate(sar->action);
                }
 
-       g_idle_add((GSourceFunc)search_and_run_destroy, sar);
+       g_idle_add(static_cast<GSourceFunc>(search_and_run_destroy), sar);
 
        return TRUE;
 }
 
 static gboolean match_func(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer data)
 {
-       SarData *sar = data;
+       auto sar = static_cast<SarData *>(data);
        gboolean ret = FALSE;
        gchar *normalized;
        GtkTreeModel *model;
@@ -246,7 +254,7 @@ static gboolean match_func(GtkEntryCompletion *completion, const gchar *key, Gtk
        gchar *label;
        GString *reg_exp_str;
        GRegex *reg_exp;
-       GError *error = NULL;
+       GError *error = nullptr;
 
        model = gtk_entry_completion_get_model(completion);
        gtk_tree_model_get(GTK_TREE_MODEL(model), iter, SAR_LABEL, &label, -1);
@@ -257,16 +265,16 @@ static gboolean match_func(GtkEntryCompletion *completion, const gchar *key, Gtk
        reg_exp_str = g_string_new("\\b(\?=.*:)");
        reg_exp_str = g_string_append(reg_exp_str, key);
 
-       reg_exp = g_regex_new(reg_exp_str->str, G_REGEX_CASELESS, 0, &error);
+       reg_exp = g_regex_new(reg_exp_str->str, G_REGEX_CASELESS, static_cast<GRegexMatchFlags>(0), &error);
        if (error)
                {
                log_printf("Error: could not compile regular expression %s\n%s\n", reg_exp_str->str, error->message);
                g_error_free(error);
-               error = NULL;
-               reg_exp = g_regex_new("", 0, 0, NULL);
+               error = nullptr;
+               reg_exp = g_regex_new("", static_cast<GRegexCompileFlags>(0), static_cast<GRegexMatchFlags>(0), nullptr);
                }
 
-       ret = g_regex_match(reg_exp, normalized, 0, NULL);
+       ret = g_regex_match(reg_exp, normalized, static_cast<GRegexMatchFlags>(0), nullptr);
 
        if (sar->match_found == FALSE && ret == TRUE)
                {
@@ -284,47 +292,25 @@ static gboolean match_func(GtkEntryCompletion *completion, const gchar *key, Gtk
 GtkWidget *search_and_run_new(LayoutWindow *lw)
 {
        SarData *sar;
-       GdkGeometry geometry;
 
        sar = g_new0(SarData, 1);
        sar->lw = lw;
-       sar->window = window_new(GTK_WINDOW_TOPLEVEL, "sar_window", NULL, NULL, _("Search and Run command"));
-       DEBUG_NAME(sar->window);
 
-       geometry.min_width = 500;
-       geometry.max_width = 1500;
-       geometry.min_height = 10;
-       geometry.max_height = 10;
-       gtk_window_set_geometry_hints(GTK_WINDOW(sar->window), NULL, &geometry, GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
-
-       gtk_window_set_resizable(GTK_WINDOW(sar->window), TRUE);
+       sar->builder = gtk_builder_new_from_resource(GQ_RESOURCE_PATH_UI "/search-and-run.ui");
+       command_store_populate(sar);
 
-       sar->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
-       gtk_container_add(GTK_CONTAINER(sar->window), sar->vbox);
-       gtk_widget_show(sar->vbox);
+       sar->window = GTK_WIDGET(gtk_builder_get_object(sar->builder, "search_and_run"));
+       DEBUG_NAME(sar->window);
 
-       sar->entry_box = gtk_entry_new();
-       gtk_box_pack_start(GTK_BOX(sar->vbox), sar->entry_box, FALSE, FALSE, 0);
-       gtk_widget_show(sar->entry_box);
-       gtk_entry_set_icon_from_stock(GTK_ENTRY(sar->entry_box), GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
-       gtk_widget_show(sar->vbox);
-       gtk_widget_set_tooltip_text(sar->entry_box, "Search for commands and run them");
-       g_signal_connect(G_OBJECT(sar->entry_box), "key_press_event", G_CALLBACK(keypress_cb), sar);
-       g_signal_connect(G_OBJECT(sar->entry_box), "activate", G_CALLBACK(entry_box_activate_cb), sar);
+       gtk_entry_completion_set_match_func(GTK_ENTRY_COMPLETION(gtk_builder_get_object(sar->builder, "completion")), match_func, sar, nullptr);
 
-       command_store_populate(sar);
-
-       sar->completion = gtk_entry_completion_new();
-       gtk_entry_set_completion(GTK_ENTRY(sar->entry_box), sar->completion);
-       gtk_entry_completion_set_inline_completion(sar->completion, FALSE);
-       gtk_entry_completion_set_inline_selection(sar->completion, FALSE);
-       gtk_entry_completion_set_minimum_key_length(sar->completion, 1);
-       gtk_entry_completion_set_match_func(sar->completion, match_func, sar, NULL);
-       g_signal_connect(G_OBJECT(sar->completion), "match-selected", G_CALLBACK(match_selected_cb), sar);
-       gtk_entry_completion_set_model(sar->completion, GTK_TREE_MODEL(sar->command_store));
-       gtk_entry_completion_set_text_column(sar->completion, SAR_LABEL);
+       g_signal_connect(G_OBJECT(gtk_builder_get_object(sar->builder, "completion")), "match-selected", G_CALLBACK(match_selected_cb), sar);
+       g_signal_connect(G_OBJECT(gtk_builder_get_object(sar->builder, "entry")), "key_press_event", G_CALLBACK(keypress_cb), sar);
+       g_signal_connect(G_OBJECT(gtk_builder_get_object(sar->builder, "entry")), "activate", G_CALLBACK(entry_box_activate_cb), sar);
 
        gtk_widget_show(sar->window);
+
        return sar->window;
 }
+
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */