[gimp] Bug 706309 - Add a “Save As” button to the “Quit GIMP” dialog
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 706309 - Add a “Save As” button to the “Quit GIMP” dialog
- Date: Sat, 1 Oct 2016 19:01:11 +0000 (UTC)
commit 0089a017f0b4b522a9e8f9fb0be8155e0a78212d
Author: Michael Natterer <mitch gimp org>
Date: Sat Oct 1 20:55:13 2016 +0200
Bug 706309 - Add a “Save As” button to the “Quit GIMP” dialog
Add GimpCellRendererButton and use it to add a "Save" icon to each row
of dirty images. Click invokes the "edit-save" action, shift-click
invokes "edit-save-as". Also add a tooltip for the icon button.
Involves minor changes to GimpContainerTreeView to allow
GimpCellRendererButton to be added, and to allow external
"query-tooltip" handlers to run.
app/dialogs/quit-dialog.c | 173 ++++++++++++++++++++++++++++++----
app/widgets/Makefile.am | 2 +
app/widgets/gimpcellrendererbutton.c | 143 ++++++++++++++++++++++++++++
app/widgets/gimpcellrendererbutton.h | 59 ++++++++++++
app/widgets/gimpcontainertreeview.c | 32 +++++--
app/widgets/widgets-types.h | 1 +
6 files changed, 384 insertions(+), 26 deletions(-)
---
diff --git a/app/dialogs/quit-dialog.c b/app/dialogs/quit-dialog.c
index df56262..d5ed14a 100644
--- a/app/dialogs/quit-dialog.c
+++ b/app/dialogs/quit-dialog.c
@@ -37,7 +37,9 @@
#include "display/gimpdisplay.h"
#include "display/gimpdisplay-foreach.h"
#include "display/gimpdisplayshell.h"
+#include "display/gimpimagewindow.h"
+#include "widgets/gimpcellrendererbutton.h"
#include "widgets/gimpcontainertreestore.h"
#include "widgets/gimpcontainertreeview.h"
#include "widgets/gimpcontainerview.h"
@@ -45,6 +47,7 @@
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpmessagebox.h"
#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpuimanager.h"
#include "widgets/gimpviewrenderer.h"
#include "widgets/gimpwidgets-utils.h"
@@ -57,20 +60,22 @@ typedef struct _QuitDialog QuitDialog;
struct _QuitDialog
{
- Gimp *gimp;
- GimpContainer *images;
- GimpContext *context;
+ Gimp *gimp;
+ GimpContainer *images;
+ GimpContext *context;
- gboolean do_quit;
+ gboolean do_quit;
- GtkWidget *dialog;
- GtkWidget *ok_button;
- GimpMessageBox *box;
- GtkWidget *lost_label;
- GtkWidget *hint_label;
-
- guint accel_key;
- GdkModifierType accel_mods;
+ GtkWidget *dialog;
+ GimpContainerTreeView *tree_view;
+ GtkTreeViewColumn *save_column;
+ GtkWidget *ok_button;
+ GimpMessageBox *box;
+ GtkWidget *lost_label;
+ GtkWidget *hint_label;
+
+ guint accel_key;
+ GdkModifierType accel_mods;
};
@@ -98,7 +103,16 @@ static void quit_close_all_dialog_name_cell_func (GtkTreeViewColumn *t
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data);
-
+static void quit_close_all_dialog_save_clicked (GtkCellRenderer *cell,
+ const gchar *path,
+ GdkModifierType state,
+ QuitDialog *dialog);
+static gboolean quit_close_all_dialog_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ QuitDialog *dialog);
/* public functions */
@@ -121,6 +135,7 @@ quit_close_all_dialog_new (Gimp *gimp,
QuitDialog *dialog;
GtkWidget *view;
GimpContainerTreeView *tree_view;
+ GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GtkWidget *dnd_widget;
GtkAccelGroup *accel_group;
@@ -187,15 +202,35 @@ quit_close_all_dialog_new (Gimp *gimp,
view = gimp_container_tree_view_new (dialog->images, dialog->context,
view_size, 1);
- tree_view = GIMP_CONTAINER_TREE_VIEW (view);
+ gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (view),
+ -1,
+ rows * (view_size + 2));
+
+ dialog->tree_view = tree_view = GIMP_CONTAINER_TREE_VIEW (view);
+
+ gtk_tree_view_column_set_expand (tree_view->main_column, TRUE);
+
renderer = gimp_container_tree_view_get_name_cell (tree_view);
gtk_tree_view_column_set_cell_data_func (tree_view->main_column,
renderer,
quit_close_all_dialog_name_cell_func,
NULL, NULL);
- gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (view),
- -1,
- rows * (view_size + 2));
+
+ dialog->save_column = column = gtk_tree_view_column_new ();
+ renderer = gimp_cell_renderer_button_new ();
+ g_object_set (renderer,
+ "icon-name", "document-save",
+ NULL);
+ gtk_tree_view_column_pack_end (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer, NULL);
+
+ gtk_tree_view_append_column (tree_view->view, column);
+ gimp_container_tree_view_add_toggle_cell (tree_view, renderer);
+
+ g_signal_connect (renderer, "clicked",
+ G_CALLBACK (quit_close_all_dialog_save_clicked),
+ dialog);
+
gtk_box_pack_start (GTK_BOX (dialog->box), view, TRUE, TRUE, 0);
gtk_widget_show (view);
@@ -208,6 +243,10 @@ quit_close_all_dialog_new (Gimp *gimp,
(GimpDndDragViewableFunc) gimp_dnd_get_drag_data,
NULL);
+ g_signal_connect (tree_view->view, "query-tooltip",
+ G_CALLBACK (quit_close_all_dialog_query_tooltip),
+ dialog);
+
if (do_quit)
dialog->lost_label = gtk_label_new (_("If you quit GIMP now, "
"these changes will be lost."));
@@ -436,3 +475,103 @@ quit_close_all_dialog_name_cell_func (GtkTreeViewColumn *tree_column,
g_object_unref (renderer);
g_free (name);
}
+
+static void
+quit_close_all_dialog_save_clicked (GtkCellRenderer *cell,
+ const gchar *path_str,
+ GdkModifierType state,
+ QuitDialog *dialog)
+{
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter (dialog->tree_view->model, &iter, path))
+ {
+ GimpViewRenderer *renderer;
+ GimpImage *image;
+ GList *list;
+
+ gtk_tree_model_get (dialog->tree_view->model, &iter,
+ GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
+ -1);
+
+ image = GIMP_IMAGE (renderer->viewable);
+ g_object_unref (renderer);
+
+ for (list = gimp_get_display_iter (dialog->gimp);
+ list;
+ list = g_list_next (list))
+ {
+ GimpDisplay *display = list->data;
+
+ if (gimp_display_get_image (display) == image)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GimpImageWindow *window = gimp_display_shell_get_window (shell);
+
+ if (window)
+ {
+ GimpUIManager *manager;
+
+ manager = gimp_image_window_get_ui_manager (window);
+
+ gimp_display_shell_present (shell);
+
+ if (state & GDK_SHIFT_MASK)
+ {
+ gimp_ui_manager_activate_action (manager, "file",
+ "file-save-as");
+ }
+ else
+ {
+ gimp_ui_manager_activate_action (manager, "file",
+ "file-save");
+ }
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+static gboolean
+quit_close_all_dialog_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ QuitDialog *dialog)
+{
+ GtkTreePath *path;
+ gboolean show_tip = FALSE;
+
+ if (gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget), &x, &y,
+ keyboard_tip,
+ NULL, &path, NULL))
+ {
+ GtkTreeViewColumn *column = NULL;
+
+ gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y,
+ NULL, &column, NULL, NULL);
+
+ if (column == dialog->save_column)
+ {
+ gchar *tip = g_strconcat (_("Save this image"), "\n<b>",
+ gimp_get_mod_string (GDK_SHIFT_MASK),
+ "</b> ", _("Save as"),
+ NULL);
+
+ gtk_tooltip_set_markup (tooltip, tip);
+ gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (widget), tooltip, path);
+
+ g_free (tip);
+
+ show_tip = TRUE;
+ }
+
+ gtk_tree_path_free (path);
+ }
+
+ return show_tip;
+}
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index 3fc7dde..c0eb8e8 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -43,6 +43,8 @@ libappwidgets_a_sources = \
gimpbufferview.h \
gimpcairo-wilber.c \
gimpcairo-wilber.h \
+ gimpcellrendererbutton.c \
+ gimpcellrendererbutton.h \
gimpcellrendererdashes.c \
gimpcellrendererdashes.h \
gimpcellrendererviewable.c \
diff --git a/app/widgets/gimpcellrendererbutton.c b/app/widgets/gimpcellrendererbutton.c
new file mode 100644
index 0000000..f9589c0
--- /dev/null
+++ b/app/widgets/gimpcellrendererbutton.c
@@ -0,0 +1,143 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpcellrendererbutton.c
+ * Copyright (C) 2016 Michael Natterer <mitch gimp org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+
+#include "widgets-types.h"
+
+#include "core/gimpmarshal.h"
+
+#include "gimpcellrendererbutton.h"
+
+
+enum
+{
+ CLICKED,
+ LAST_SIGNAL
+};
+
+
+static gboolean gimp_cell_renderer_button_activate (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags);
+
+
+G_DEFINE_TYPE (GimpCellRendererButton, gimp_cell_renderer_button,
+ GTK_TYPE_CELL_RENDERER_PIXBUF)
+
+#define parent_class gimp_cell_renderer_button_parent_class
+
+static guint button_cell_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+gimp_cell_renderer_button_class_init (GimpCellRendererButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
+
+ /**
+ * GimpCellRendererButton::clicked:
+ * @cell:
+ * @path:
+ * @state:
+ *
+ * Called on a button cell when it is clicked.
+ **/
+ button_cell_signals[CLICKED] =
+ g_signal_new ("clicked",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GimpCellRendererButtonClass, clicked),
+ NULL, NULL,
+ gimp_marshal_VOID__STRING_FLAGS,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ GDK_TYPE_MODIFIER_TYPE);
+
+ cell_class->activate = gimp_cell_renderer_button_activate;
+
+ klass->clicked = NULL;
+}
+
+static void
+gimp_cell_renderer_button_init (GimpCellRendererButton *cell_button)
+{
+ g_object_set (cell_button,
+ "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
+ "xpad", 2,
+ "ypad", 2,
+ "follow-state", TRUE,
+ "stock-size", GTK_ICON_SIZE_BUTTON,
+ NULL);
+}
+
+static gboolean
+gimp_cell_renderer_button_activate (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ GimpCellRendererButton *cell_button = GIMP_CELL_RENDERER_BUTTON (cell);
+ GdkModifierType state = 0;
+
+ if (event && ((GdkEventAny *) event)->type == GDK_BUTTON_PRESS)
+ state = ((GdkEventButton *) event)->state;
+
+ if (! event ||
+ (((GdkEventAny *) event)->type == GDK_BUTTON_PRESS &&
+ ((GdkEventButton *) event)->button == 1))
+ {
+ gimp_cell_renderer_button_clicked (cell_button, path, state);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* public functions */
+
+GtkCellRenderer *
+gimp_cell_renderer_button_new (void)
+{
+ return g_object_new (GIMP_TYPE_CELL_RENDERER_BUTTON, NULL);
+}
+
+void
+gimp_cell_renderer_button_clicked (GimpCellRendererButton *cell,
+ const gchar *path,
+ GdkModifierType state)
+{
+ g_return_if_fail (GIMP_IS_CELL_RENDERER_BUTTON (cell));
+ g_return_if_fail (path != NULL);
+
+ g_signal_emit (cell, button_cell_signals[CLICKED], 0, path, state);
+}
diff --git a/app/widgets/gimpcellrendererbutton.h b/app/widgets/gimpcellrendererbutton.h
new file mode 100644
index 0000000..9ce430f
--- /dev/null
+++ b/app/widgets/gimpcellrendererbutton.h
@@ -0,0 +1,59 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpcellrendererbutton.h
+ * Copyright (C) 2016 Michael Natterer <mitch gimp org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_CELL_RENDERER_BUTTON_H__
+#define __GIMP_CELL_RENDERER_BUTTON_H__
+
+
+#define GIMP_TYPE_CELL_RENDERER_BUTTON (gimp_cell_renderer_button_get_type ())
+#define GIMP_CELL_RENDERER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GIMP_TYPE_CELL_RENDERER_BUTTON, GimpCellRendererButton))
+#define GIMP_CELL_RENDERER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GIMP_TYPE_CELL_RENDERER_BUTTON, GimpCellRendererButtonClass))
+#define GIMP_IS_CELL_RENDERER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GIMP_TYPE_CELL_RENDERER_BUTTON))
+#define GIMP_IS_CELL_RENDERER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GIMP_TYPE_CELL_RENDERER_BUTTON))
+#define GIMP_CELL_RENDERER_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GIMP_TYPE_CELL_RENDERER_BUTTON, GimpCellRendererButtonClass))
+
+
+typedef struct _GimpCellRendererButtonClass GimpCellRendererButtonClass;
+
+struct _GimpCellRendererButton
+{
+ GtkCellRendererPixbuf parent_instance;
+};
+
+struct _GimpCellRendererButtonClass
+{
+ GtkCellRendererPixbufClass parent_class;
+
+ void (* clicked) (GimpCellRendererButton *cell,
+ const gchar *path,
+ GdkModifierType state);
+};
+
+
+GType gimp_cell_renderer_button_get_type (void) G_GNUC_CONST;
+
+GtkCellRenderer * gimp_cell_renderer_button_new (void);
+
+void gimp_cell_renderer_button_clicked (GimpCellRendererButton *cell,
+ const gchar *path,
+ GdkModifierType state);
+
+
+#endif /* __GIMP_CELL_RENDERER_BUTTON_H__ */
diff --git a/app/widgets/gimpcontainertreeview.c b/app/widgets/gimpcontainertreeview.c
index f56fa4f..5901460 100644
--- a/app/widgets/gimpcontainertreeview.c
+++ b/app/widgets/gimpcontainertreeview.c
@@ -35,6 +35,7 @@
#include "core/gimpmarshal.h"
#include "core/gimpviewable.h"
+#include "gimpcellrendererbutton.h"
#include "gimpcellrendererviewable.h"
#include "gimpcontainertreestore.h"
#include "gimpcontainertreeview.h"
@@ -321,9 +322,12 @@ gimp_container_tree_view_constructed (GObject *object)
G_CALLBACK (gimp_container_tree_view_drag_data_received),
tree_view);
- g_signal_connect (tree_view->view, "query-tooltip",
- G_CALLBACK (gimp_container_tree_view_tooltip),
- tree_view);
+ /* connect_after so external code can connect to "query-tooltip" too
+ * and override the default tip
+ */
+ g_signal_connect_after (tree_view->view, "query-tooltip",
+ G_CALLBACK (gimp_container_tree_view_tooltip),
+ tree_view);
}
static void
@@ -520,7 +524,8 @@ gimp_container_tree_view_add_toggle_cell (GimpContainerTreeView *tree_view,
GtkCellRenderer *cell)
{
g_return_if_fail (GIMP_IS_CONTAINER_TREE_VIEW (tree_view));
- g_return_if_fail (GIMP_IS_CELL_RENDERER_TOGGLE (cell));
+ g_return_if_fail (GIMP_IS_CELL_RENDERER_TOGGLE (cell) ||
+ GIMP_IS_CELL_RENDERER_BUTTON (cell));
tree_view->priv->toggle_cells = g_list_prepend (tree_view->priv->toggle_cells,
cell);
@@ -1043,7 +1048,7 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
&path, &column, NULL, NULL))
{
GimpViewRenderer *renderer;
- GimpCellRendererToggle *toggled_cell = NULL;
+ GtkCellRenderer *toggled_cell = NULL;
GimpCellRendererViewable *clicked_cell = NULL;
GtkCellRenderer *edit_cell = NULL;
GdkRectangle column_area;
@@ -1098,7 +1103,7 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
g_list_free (cells);
}
- toggled_cell = (GimpCellRendererToggle *)
+ toggled_cell =
gimp_container_tree_view_find_click_cell (widget,
tree_view->priv->toggle_cells,
column, &column_area,
@@ -1181,9 +1186,18 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
if (toggled_cell)
{
- gimp_cell_renderer_toggle_clicked (toggled_cell,
- path_str,
- bevent->state);
+ if (GIMP_IS_CELL_RENDERER_TOGGLE (toggled_cell))
+ {
+ gimp_cell_renderer_toggle_clicked (GIMP_CELL_RENDERER_TOGGLE (toggled_cell),
+ path_str,
+ bevent->state);
+ }
+ else if (GIMP_IS_CELL_RENDERER_BUTTON (toggled_cell))
+ {
+ gimp_cell_renderer_button_clicked (GIMP_CELL_RENDERER_BUTTON (toggled_cell),
+ path_str,
+ bevent->state);
+ }
}
else if (clicked_cell)
{
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index d617088..8989e1f 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -240,6 +240,7 @@ typedef struct _GimpViewRendererVectors GimpViewRendererVectors;
/* cell renderers */
+typedef struct _GimpCellRendererButton GimpCellRendererButton;
typedef struct _GimpCellRendererDashes GimpCellRendererDashes;
typedef struct _GimpCellRendererViewable GimpCellRendererViewable;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]