clang-tidy; -bugprone-suspicious-string-compare, misc-unused-parameters
[geeqie.git] / src / layout-util.cc
index 8dfac9c..5dc2ff5 100644 (file)
@@ -904,6 +904,95 @@ static void layout_menu_view_in_new_window_cb(GtkAction *, gpointer data)
        view_window_new(layout_image_get_fd(lw));
 }
 
+struct OpenWithData
+{
+       GAppInfo *application;
+       GList *g_file_list;
+       GtkWidget *app_chooser_dialog;
+};
+
+void open_with_response_cb(GtkDialog *, gint response_id, gpointer data)
+{
+       GError *error = nullptr;
+       auto open_with_data = static_cast<OpenWithData *>(data);
+
+       if (response_id == GTK_RESPONSE_OK)
+               {
+               g_app_info_launch(open_with_data->application, open_with_data->g_file_list, nullptr, &error);
+
+               if (error)
+                       {
+                       log_printf("Error launching app: %s\n", error->message);
+                       g_error_free(error);
+                       }
+               }
+
+       g_object_unref(open_with_data->application);
+       g_object_unref(g_list_first(open_with_data->g_file_list)->data);
+       g_list_free(open_with_data->g_file_list);
+       gtk_widget_destroy(GTK_WIDGET(open_with_data->app_chooser_dialog));
+       g_free(open_with_data);
+}
+
+static void open_with_application_selected_cb(GtkAppChooserWidget *, GAppInfo *application, gpointer data)
+{
+       auto open_with_data = static_cast<OpenWithData *>(data);
+
+       g_object_unref(open_with_data->application);
+
+       open_with_data->application = g_app_info_dup(application);
+}
+
+static void open_with_application_activated_cb(GtkAppChooserWidget *, GAppInfo *application, gpointer data)
+{
+       GError *error = nullptr;
+       auto open_with_data = static_cast<OpenWithData *>(data);
+
+       g_app_info_launch(application, open_with_data->g_file_list, nullptr, &error);
+
+       if (error)
+               {
+               log_printf("Error launching app.: %s\n", error->message);
+               g_error_free(error);
+               }
+
+       g_object_unref(open_with_data->application);
+       g_object_unref(g_list_first(open_with_data->g_file_list)->data);
+       g_list_free(open_with_data->g_file_list);
+       gtk_widget_destroy(GTK_WIDGET(open_with_data->app_chooser_dialog));
+       g_free(open_with_data);
+}
+
+static void layout_menu_open_with_cb(GtkAction *, gpointer data)
+{
+       auto lw = static_cast<LayoutWindow *>(data);
+       FileData *fd;
+       GtkWidget *widget;
+       OpenWithData *open_with_data;
+
+       if (layout_selection_list(lw))
+               {
+               open_with_data = g_new(OpenWithData, 1);
+
+               fd = static_cast<FileData *>(g_list_first(layout_selection_list(lw))->data);
+
+               open_with_data->g_file_list = g_list_append(nullptr, g_file_new_for_path(fd->path));
+
+               open_with_data->app_chooser_dialog = gtk_app_chooser_dialog_new(nullptr, GTK_DIALOG_DESTROY_WITH_PARENT, G_FILE(g_list_first(open_with_data->g_file_list)->data));
+
+               widget = gtk_app_chooser_dialog_get_widget(GTK_APP_CHOOSER_DIALOG(open_with_data->app_chooser_dialog));
+
+               open_with_data->application = gtk_app_chooser_get_app_info(GTK_APP_CHOOSER(open_with_data->app_chooser_dialog));
+
+               g_signal_connect(G_OBJECT(widget), "application-selected", G_CALLBACK(open_with_application_selected_cb), open_with_data);
+               g_signal_connect(G_OBJECT(widget), "application-activated", G_CALLBACK(open_with_application_activated_cb), open_with_data);
+               g_signal_connect(G_OBJECT(open_with_data->app_chooser_dialog), "response", G_CALLBACK(open_with_response_cb), open_with_data);
+               g_signal_connect(G_OBJECT(open_with_data->app_chooser_dialog), "close", G_CALLBACK(open_with_response_cb), open_with_data);
+
+               gtk_widget_show(open_with_data->app_chooser_dialog);
+               }
+}
+
 static void layout_menu_open_archive_cb(GtkAction *, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
@@ -1947,7 +2036,7 @@ static void layout_menu_collection_recent_update(LayoutWindow *lw)
                menu_item_add(menu, _("Empty"), nullptr, nullptr);
                }
 
-       recent = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/FileMenu/OpenRecent");
+       recent = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/FileMenu/OpenRecent" : "/MainMenu/FileMenu/OpenRecent");
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent), menu);
        gtk_widget_set_sensitive(recent, (n != 0));
 }
@@ -2003,7 +2092,7 @@ static void layout_menu_collection_open_update(LayoutWindow *lw)
                menu_item_add(menu, _("Empty"), nullptr, nullptr);
                }
 
-       recent = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/FileMenu/OpenCollection");
+       recent = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/FileMenu/OpenCollection" : "/MainMenu/FileMenu/OpenCollection");
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent), menu);
        gtk_widget_set_sensitive(recent, (n != 0));
 }
@@ -2162,7 +2251,7 @@ static void layout_menu_new_window_update(LayoutWindow *lw)
 
        list = layout_window_menu_list(list);
 
-       menu = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/WindowsMenu/NewWindow");
+       menu = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/WindowsMenu/NewWindow" : "/MainMenu/WindowsMenu/NewWindow");
        sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
 
        children = gtk_container_get_children(GTK_CONTAINER(sub_menu));
@@ -2307,7 +2396,8 @@ static void layout_menu_windows_menu_cb(GtkWidget *, gpointer data)
        GList *children, *iter;
        gint i;
 
-       menu = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/WindowsMenu/");
+       menu = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/WindowsMenu/" : "/MainMenu/WindowsMenu/");
+
        sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
 
        /* disable Delete for temporary windows */
@@ -2338,7 +2428,7 @@ static void layout_menu_view_menu_cb(GtkWidget *, gpointer data)
        gint i;
        FileData *fd;
 
-       menu = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/ViewMenu/");
+       menu = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/ViewMenu/" : "/MainMenu/ViewMenu/");
        sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
 
        fd = layout_image_get_fd(lw);
@@ -2607,7 +2697,9 @@ static GtkActionEntry menu_entries[] = {
   { "NextPage",              GQ_ICON_FORWARD_PAGE,              N_("_Next Page"),                                       nullptr,               N_("Next Page of multi-page image"),                   CB(layout_menu_page_next_cb) },
   { "OpenArchive",           GQ_ICON_OPEN,                      N_("Open archive"),                                     nullptr,               N_("Open archive"),                                    CB(layout_menu_open_archive_cb) },
   { "OpenCollection",        GQ_ICON_OPEN,                      N_("_Open collection..."),                              "O",                   N_("Open collection..."),                              nullptr },
+  { "OpenMenu",              nullptr,                           N_("☰"),                                                nullptr,               nullptr,                                               nullptr },
   { "OpenRecent",            nullptr,                           N_("Open recen_t"),                                     nullptr,               N_("Open recent collection"),                          nullptr },
+  { "OpenWith",              GQ_ICON_OPEN_WITH,                 N_("Open With..."),                                     nullptr,               N_("Open With..."),                                    CB(layout_menu_open_with_cb) },
   { "OrientationMenu",       nullptr,                           N_("_Orientation"),                                     nullptr,               nullptr,                                               nullptr },
   { "OverlayMenu",           nullptr,                           N_("Image _Overlay"),                                   nullptr,               nullptr,                                               nullptr },
   { "PanView",               PIXBUF_INLINE_ICON_PANORAMA,       N_("Pa_n view"),                                        "<control>J",          N_("Pan view"),                                        CB(layout_menu_pan_cb) },
@@ -2790,8 +2882,13 @@ static void layout_actions_setup_marks(LayoutWindow *lw)
        GError *error;
        GString *desc = g_string_new(
                                "<ui>"
-                               "  <menubar name='MainMenu'>"
-                               "    <menu action='SelectMenu'>");
+                               "  <menubar name='MainMenu'>");
+
+       if (options->hamburger_menu)
+               {
+               g_string_append(desc, "    <menu action='OpenMenu'>");
+               }
+       g_string_append(desc, "      <menu action='SelectMenu'>");
 
        for (mark = 1; mark <= FILEDATA_MARKS_SIZE; mark++)
                {
@@ -2826,8 +2923,13 @@ static void layout_actions_setup_marks(LayoutWindow *lw)
                }
 
        g_string_append(desc,
-                               "    </menu>"
-                               "  </menubar>");
+                               "      </menu>");
+       if (options->hamburger_menu)
+               {
+               g_string_append(desc, "    </menu>");
+               }
+       g_string_append(desc, "  </menubar>");
+
        for (mark = 1; mark <= FILEDATA_MARKS_SIZE; mark++)
                {
                gint i = (mark < 10 ? mark : 0);
@@ -2957,6 +3059,11 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
                                "<ui>"
                                "  <menubar name='MainMenu'>");
 
+       if (options->hamburger_menu)
+               {
+               g_string_append(desc, "    <menu action='OpenMenu'>");
+               }
+
        editors_list = editor_list_get();
 
        old_path = nullptr;
@@ -2989,7 +3096,12 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
        layout_actions_editor_add(desc, nullptr, old_path);
        g_list_free_full(old_path, g_free);
 
-       g_string_append(desc,   "  </menubar>"
+       if (options->hamburger_menu)
+               {
+               g_string_append(desc, "</menu>");
+               }
+
+       g_string_append(desc,"  </menubar>"
                                "</ui>" );
 
        error = nullptr;
@@ -3049,7 +3161,8 @@ void layout_actions_setup(LayoutWindow *lw)
 
        DEBUG_1("%s layout_actions_setup: add menu", get_exec_time());
        error = nullptr;
-       if (!gtk_ui_manager_add_ui_from_resource(lw->ui_manager, GQ_RESOURCE_PATH_UI "/menu.ui", &error))
+
+       if (!gtk_ui_manager_add_ui_from_resource(lw->ui_manager, options->hamburger_menu ? GQ_RESOURCE_PATH_UI "/menu-hamburger.ui" : GQ_RESOURCE_PATH_UI "/menu-classic.ui" , &error))
                {
                g_message("building menus failed: %s", error->message);
                g_error_free(error);
@@ -3168,20 +3281,10 @@ GtkWidget *layout_actions_menu_bar(LayoutWindow *lw)
 GtkWidget *layout_actions_toolbar(LayoutWindow *lw, ToolbarType type)
 {
        if (lw->toolbar[type]) return lw->toolbar[type];
-       switch (type)
-               {
-               case TOOLBAR_MAIN:
-                       lw->toolbar[type] = gtk_ui_manager_get_widget(lw->ui_manager, "/ToolBar");
-                       gtk_toolbar_set_style(GTK_TOOLBAR(lw->toolbar[type]), GTK_TOOLBAR_ICONS);
-                       break;
-               case TOOLBAR_STATUS:
-                       lw->toolbar[type] = gtk_ui_manager_get_widget(lw->ui_manager, "/StatusBar");
-                       gtk_toolbar_set_style(GTK_TOOLBAR(lw->toolbar[type]), GTK_TOOLBAR_ICONS);
-                       gtk_toolbar_set_show_arrow(GTK_TOOLBAR(lw->toolbar[type]), FALSE);
-                       break;
-               default:
-                       break;
-               }
+
+       lw->toolbar[type] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+
+       gtk_widget_show(lw->toolbar[type]);
        g_object_ref(lw->toolbar[type]);
        return lw->toolbar[type];
 }
@@ -3193,19 +3296,38 @@ GtkWidget *layout_actions_menu_tool_bar(LayoutWindow *lw)
 
        if (lw->menu_tool_bar) return lw->menu_tool_bar;
 
-       menu_bar = layout_actions_menu_bar(lw);
-       DEBUG_NAME(menu_bar);
        toolbar = layout_actions_toolbar(lw, TOOLBAR_MAIN);
        DEBUG_NAME(toolbar);
        lw->menu_tool_bar = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
 
-       gq_gtk_box_pack_start(GTK_BOX(lw->menu_tool_bar), menu_bar, FALSE, FALSE, 0);
+       if (!options->hamburger_menu)
+               {
+               menu_bar = layout_actions_menu_bar(lw);
+               DEBUG_NAME(menu_bar);
+               gq_gtk_box_pack_start(GTK_BOX(lw->menu_tool_bar), menu_bar, FALSE, FALSE, 0);
+               }
+
        gq_gtk_box_pack_start(GTK_BOX(lw->menu_tool_bar), toolbar, FALSE, FALSE, 0);
 
        g_object_ref(lw->menu_tool_bar);
        return lw->menu_tool_bar;
 }
 
+void toolbar_clear_cb(GtkWidget *widget, gpointer)
+{
+       GtkAction *action;
+
+       if (GTK_IS_BUTTON(widget))
+               {
+               action = static_cast<GtkAction *>(g_object_get_data(G_OBJECT(widget), "action"));
+               if (g_object_get_data(G_OBJECT(widget), "id") )
+                       {
+                       g_signal_handler_disconnect(action, GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(widget), "id")));
+                       }
+               }
+       gtk_widget_destroy(widget);
+}
+
 void layout_toolbar_clear(LayoutWindow *lw, ToolbarType type)
 {
        if (lw->toolbar_merge_id[type])
@@ -3217,22 +3339,58 @@ void layout_toolbar_clear(LayoutWindow *lw, ToolbarType type)
        lw->toolbar_actions[type] = nullptr;
 
        lw->toolbar_merge_id[type] = gtk_ui_manager_new_merge_id(lw->ui_manager);
+
+       if (lw->toolbar[type])
+               {
+               gtk_container_foreach(GTK_CONTAINER(lw->toolbar[type]), (GtkCallback)G_CALLBACK(toolbar_clear_cb), nullptr);
+               }
 }
 
-/* Used to create a unique name for toolbar separators */
-static gint i = 0;
+void action_radio_changed_cb(GtkAction *action, GtkAction *current, gpointer data)
+{
+       auto button = static_cast<GtkToggleButton *>(data);
 
-void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action)
+       if (action == current )
+               {
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+               }
+       else
+               {
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
+               }
+}
+
+void action_toggle_activate_cb(GtkAction* self, gpointer data)
+{
+       auto button = static_cast<GtkToggleButton *>(data);
+
+       if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(self)) != gtk_toggle_button_get_active(button))
+               {
+               gtk_toggle_button_set_active(button, gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(self)));
+               }
+}
+
+gboolean toolbar_button_press_event_cb(GtkWidget *, GdkEvent *, gpointer data)
+{
+       gtk_action_activate(GTK_ACTION(data));
+
+       return TRUE;
+}
+
+void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action_name)
 {
        const gchar *path = nullptr;
-       gchar *separator_name;
+       const gchar *tooltip_text = nullptr;
+       GtkAction *action;
+       GtkWidget *action_icon = nullptr;
+       GtkWidget *button;
+       gulong id;
 
-       if (!action || !lw->ui_manager) return;
+       if (!action_name || !lw->ui_manager) return;
 
-       /* There can be multiple separators, but only a single of others */
-       if (g_strcmp0(action, "Separator") != 0)
+       if (!lw->toolbar[type])
                {
-               if (g_list_find_custom(lw->toolbar_actions[type], action, reinterpret_cast<GCompareFunc>(strcmp))) return;
+               return;
                }
 
        switch (type)
@@ -3247,8 +3405,7 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action)
                        break;
                }
 
-
-       if (g_str_has_suffix(action, ".desktop"))
+       if (g_str_has_suffix(action_name, ".desktop"))
                {
                /* this may be called before the external editors are read
                   create a dummy action for now */
@@ -3257,37 +3414,79 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action)
                        lw->action_group_editors = gtk_action_group_new("MenuActionsExternal");
                        gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
                        }
-               if (!gtk_action_group_get_action(lw->action_group_editors, action))
+               if (!gtk_action_group_get_action(lw->action_group_editors, action_name))
                        {
-                       GtkActionEntry entry = { action,
+                       GtkActionEntry entry = { action_name,
                                                 GQ_ICON_MISSING_IMAGE,
-                                                action,
+                                                action_name,
                                                 nullptr,
                                                 nullptr,
-                                                nullptr };
-                       DEBUG_1("Creating temporary action %s", action);
+                                                nullptr
+                                              };
+                       DEBUG_1("Creating temporary action %s", action_name);
                        gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw);
                        }
                }
 
-       if (g_strcmp0(action, "Separator") == 0)
+       if (g_strcmp0(action_name, "Separator") == 0)
                {
-               /* gtk_ui_manager requires items to have unique names */
-               i++;
-               separator_name = g_strdup_printf("separator_%i",i);
-
-               gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, separator_name, NULL, GTK_UI_MANAGER_SEPARATOR, FALSE);
-
-               g_free(separator_name);
+               button = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
                }
        else
                {
-               gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, action, action, GTK_UI_MANAGER_TOOLITEM, FALSE);
+               action = gtk_action_group_get_action(lw->action_group, action_name);
+
+               action_icon = gtk_action_create_icon(action, GTK_ICON_SIZE_SMALL_TOOLBAR);
+               tooltip_text = gtk_action_get_tooltip(action);
+
+               gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, action_name, action_name, GTK_UI_MANAGER_TOOLITEM, FALSE);
+
+               if (GTK_IS_RADIO_ACTION(action) || GTK_IS_TOGGLE_ACTION(action))
+                       {
+                       button = gtk_toggle_button_new();
+                       }
+               else
+                       {
+                       button = gtk_button_new();
+                       }
+
+               if (GTK_IS_TOGGLE_ACTION(action) || GTK_IS_RADIO_ACTION(action))
+                       {
+                       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
+                       }
+
+               if (action_icon)
+                       {
+                       gtk_button_set_image(GTK_BUTTON(button), action_icon);
+                       }
+               else
+                       {
+                       gtk_button_set_label(GTK_BUTTON(button), action_name);
+                       }
+
+               gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+               gtk_widget_set_tooltip_text(button, tooltip_text);
+
+               if (GTK_IS_RADIO_ACTION(action))
+                       {
+                       id = g_signal_connect(G_OBJECT(action), "changed", G_CALLBACK(action_radio_changed_cb), button);
+                       g_object_set_data(G_OBJECT(button), "id", GUINT_TO_POINTER(id));
+                       }
+               else if (GTK_IS_TOGGLE_ACTION(action))
+                       {
+                       id = g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(action_toggle_activate_cb), button);
+                       g_object_set_data(G_OBJECT(button), "id", GUINT_TO_POINTER(id));
+                       }
+
+               g_signal_connect(G_OBJECT(button), "button_press_event", G_CALLBACK(toolbar_button_press_event_cb), action);
+               g_object_set_data(G_OBJECT(button), "action", action);
                }
 
-       lw->toolbar_actions[type] = g_list_append(lw->toolbar_actions[type], g_strdup(action));
-}
+       gq_gtk_container_add(GTK_WIDGET(lw->toolbar[type]), GTK_WIDGET(button));
+       gtk_widget_show(GTK_WIDGET(button));
 
+       lw->toolbar_actions[type] = g_list_append(lw->toolbar_actions[type], g_strdup(action_name));
+}
 
 void layout_toolbar_add_default(LayoutWindow *lw, ToolbarType type)
 {