Hello Tristan
Have written code for the management of all the GtkAction sensitivities
in the user interface.
Overview
--------
1. Separated all the menu actions into two action groups:
The actions in the 'static_actions' group are always sensitive,
since the user should be able activate them even if
no project is open.
The actions in the 'project_actions' group are desensitized when
all projects have been closed.
2. Detection of read-only files. Can now preempt users from trying to
save a read-only project file.
3. Detection of correct state so that Cut/Copy/Paste/Delete actions
can be carried out.
4. Hacked on the Undo/Redo code. No more "Undo: " labels if there
is no command description.
ChangeLog Entry
---------------
2006-04-07 Vincent Geddes <[EMAIL PROTECTED]>
* src/glade-project-window.c:
o Manage the sensitivities of all the ui actions.
o Fix some issues with the Undo & Redo actions.
* src/glade-project.[ch]:
o Detect if project file is read-only. New property
"read-only"
o Detect if project has a selection. New property
"has-selection"
* src/glade-clipboard.[ch]:
o Detect if clipboard has selected items to paste.
New property "has-selection"
* src/glade-utils.h: New function:
glade_util_file_is_writeable ().
Cheers
Vincent Geddes
Index: src/glade-utils.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-utils.c,v
retrieving revision 1.73
diff -u -p -r1.73 glade-utils.c
--- src/glade-utils.c 5 Apr 2006 19:40:44 -0000 1.73
+++ src/glade-utils.c 9 Apr 2006 12:14:29 -0000
@@ -29,6 +29,7 @@
#include <gmodule.h>
#include <glib/gi18n-lib.h>
#include <glib/gstdio.h>
+#include <unistd.h>
#include <errno.h>
#include "glade.h"
@@ -1476,4 +1477,20 @@ glade_util_load_library (const gchar *li
}
return module;
+}
+
+/**
+ * glade_util_file_is_writeable:
+ * @path: the path to the file
+ *
+ * Checks whether the file at @path is writeable
+ *
+ * Returns: TRUE if file is writeable
+ */
+gboolean
+glade_util_file_is_writeable (const gchar *path)
+{
+ g_assert (path != NULL);
+
+ return g_access (path, W_OK) == 0;
}
Index: src/glade-utils.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-utils.h,v
retrieving revision 1.44
diff -u -p -r1.44 glade-utils.h
--- src/glade-utils.h 3 Apr 2006 19:56:02 -0000 1.44
+++ src/glade-utils.h 9 Apr 2006 12:14:29 -0000
@@ -118,6 +118,9 @@ gboolean glade_util_copy_file
LIBGLADEUI_API
GModule *glade_util_load_library (const gchar *library_name);
+LIBGLADEUI_API
+gboolean glade_util_file_is_writeable (const gchar *path);
+
G_END_DECLS
#endif /* __GLADE_UTILS_H__ */
Index: src/glade-project.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project.c,v
retrieving revision 1.96
diff -u -p -r1.96 glade-project.c
--- src/glade-project.c 29 Mar 2006 22:15:41 -0000 1.96
+++ src/glade-project.c 9 Apr 2006 12:14:53 -0000
@@ -63,7 +63,9 @@ enum
enum
{
PROP_0,
- PROP_HAS_UNSAVED_CHANGES
+ PROP_HAS_UNSAVED_CHANGES,
+ PROP_HAS_SELECTION,
+ PROP_READ_ONLY
};
static guint glade_project_signals[LAST_SIGNAL] = {0};
@@ -82,7 +84,13 @@ glade_project_get_property (GObject *
{
case PROP_HAS_UNSAVED_CHANGES:
g_value_set_boolean (value, project->changed);
+ break;
+ case PROP_HAS_SELECTION:
+ g_value_set_boolean (value, project->has_selection);
break;
+ case PROP_READ_ONLY:
+ g_value_set_boolean (value, project->readonly);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -261,6 +269,22 @@ glade_project_class_init (GladeProjectCl
FALSE,
G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_HAS_SELECTION,
+ g_param_spec_boolean ("has-selection",
+ "Has Selection",
+ "Whether project has a selection",
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_READ_ONLY,
+ g_param_spec_boolean ("read-only",
+ "Read Only",
+ "Whether project is read only or not",
+ FALSE,
+ G_PARAM_READABLE));
+
object_class->finalize = glade_project_finalize;
@@ -282,8 +306,10 @@ glade_project_init (GladeProject *projec
project->name = NULL;
project->instance = 0;
project->untitled_number = 0;
+ project->readonly = FALSE;
project->objects = NULL;
project->selection = NULL;
+ project->has_selection = FALSE;
project->undo_stack = NULL;
project->prev_redo_item = NULL;
project->widget_names_allocator =
@@ -332,6 +358,34 @@ glade_project_release_untitled_number (g
g_hash_table_remove (allocated_untitled_numbers, GINT_TO_POINTER (n));
}
+static void
+glade_project_set_readonly (GladeProject *project, gboolean readonly)
+{
+ g_assert (GLADE_IS_PROJECT (project));
+
+ if (project->readonly != readonly)
+ {
+ project->readonly = readonly;
+ g_object_notify (G_OBJECT (project), "read-only");
+ }
+}
+
+/**
+ * glade_project_get_readonly:
+ * @project: a #GladeProject
+ *
+ * Gets whether the project is read only or not
+ *
+ * Returns: TRUE if project is read only
+ */
+gboolean
+glade_project_get_readonly (GladeProject *project)
+{
+ g_assert (project != NULL);
+
+ return project->readonly;
+}
+
/**
* glade_project_new:
* @untitled: Whether or not this project is untitled
@@ -832,6 +886,32 @@ glade_project_new_widget_name (GladeProj
return NULL;
}
+void
+glade_project_set_has_selection (GladeProject *project, gboolean has_selection)
+{
+ g_assert (GLADE_IS_PROJECT (project));
+
+ if (project->has_selection != has_selection)
+ {
+ project->has_selection = has_selection;
+ g_object_notify (G_OBJECT (project), "has-selection");
+ }
+}
+
+/**
+ * glade_project_get_has_selection:
+ * @project: a #GladeProject
+ *
+ * Returns: whether @project currently has a selection
+ */
+gboolean
+glade_project_get_has_selection (GladeProject *project)
+{
+ g_assert (GLADE_IS_PROJECT (project));
+
+ return project->has_selection;
+}
+
/**
* glade_project_is_selected:
* @project: a #GladeProject
@@ -867,6 +947,7 @@ glade_project_selection_clear (GladeProj
g_list_free (project->selection);
project->selection = NULL;
+ glade_project_set_has_selection (project, FALSE);
if (emit_signal)
glade_project_selection_changed (project);
@@ -896,6 +977,8 @@ glade_project_selection_remove (GladePro
if (GTK_IS_WIDGET (object))
glade_util_remove_selection (GTK_WIDGET (object));
project->selection = g_list_remove (project->selection, object);
+ if (project->selection == NULL)
+ glade_project_set_has_selection (project, FALSE);
if (emit_signal)
glade_project_selection_changed (project);
}
@@ -925,6 +1008,8 @@ glade_project_selection_add (GladeProjec
{
if (GTK_IS_WIDGET (object))
glade_util_add_selection (GTK_WIDGET (object));
+ if (project->selection == NULL)
+ glade_project_set_has_selection (project, TRUE);
project->selection = g_list_prepend (project->selection, object);
if (emit_signal)
glade_project_selection_changed (project);
@@ -953,6 +1038,9 @@ glade_project_selection_set (GladeProjec
if (g_list_find (project->objects, object) == NULL)
return;
+ if (project->selection == NULL)
+ glade_project_set_has_selection (project, TRUE);
+
if (glade_project_is_selected (project, object) == FALSE ||
g_list_length (project->selection) != 1)
{
@@ -1218,6 +1306,9 @@ glade_project_open (const gchar *path)
}
+ if (glade_util_file_is_writeable (project->path) == FALSE)
+ glade_project_set_readonly (project, TRUE);
+
if (project) project->changed = FALSE;
return project;
@@ -1308,6 +1399,9 @@ glade_project_save (GladeProject *projec
g_path_get_basename (project->path));
}
+
+ glade_project_set_readonly (project,
+ !glade_util_file_is_writeable (project->path));
if (project->changed)
{
Index: src/glade-project.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project.h,v
retrieving revision 1.49
diff -u -p -r1.49 glade-project.h
--- src/glade-project.h 20 Mar 2006 17:03:08 -0000 1.49
+++ src/glade-project.h 9 Apr 2006 12:14:55 -0000
@@ -30,6 +30,8 @@ struct _GladeProject
gint untitled_number; /* A unique number for this project if it is untitled */
+ gboolean readonly; /* A flag that is set if the project is readonly */
+
gboolean loading;/* A flags that is set when the project is loading */
gboolean changed; /* A flag that is set when a project has changes
@@ -49,6 +51,8 @@ struct _GladeProject
* of #GtkWidget items.
*/
+ gboolean has_selection; /* Whether the project has a selection */
+
GList *undo_stack; /* A stack with the last executed commands */
GList *prev_redo_item; /* Points to the item previous to the redo items */
GHashTable *widget_names_allocator; /* hash table with the used widget names */
@@ -93,6 +97,8 @@ gboolean glade_project_save
LIBGLADEUI_API
void glade_project_reset_path (GladeProject *project);
LIBGLADEUI_API
+gboolean glade_project_get_readonly (GladeProject *project);
+LIBGLADEUI_API
void glade_project_add_object (GladeProject *project,
GladeProject *old_project,
GObject *object);
@@ -136,7 +142,8 @@ LIBGLADEUI_API
void glade_project_selection_changed (GladeProject *project);
LIBGLADEUI_API
GList *glade_project_selection_get (GladeProject *project);
-
+LIBGLADEUI_API
+gboolean glade_project_get_has_selection (GladeProject *project);
LIBGLADEUI_API
void glade_project_set_accel_group (GladeProject *project,
GtkAccelGroup *accel_group);
Index: src/glade-project-window.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project-window.c,v
retrieving revision 1.138
diff -u -p -r1.138 glade-project-window.c
--- src/glade-project-window.c 5 Apr 2006 20:48:55 -0000 1.138
+++ src/glade-project-window.c 9 Apr 2006 12:15:07 -0000
@@ -37,9 +37,10 @@
#define CONFIG_RECENT_PROJECTS "Recent Projects"
#define CONFIG_RECENT_PROJECTS_MAX "max_recent_projects"
-#define GLADE_ACTION_GROUP_MENU "GladeMenu"
+#define GLADE_ACTION_GROUP_STATIC "GladeStatic"
#define GLADE_ACTION_GROUP_PROJECT "GladeProject"
#define GLADE_ACTION_GROUP_RECENT "GladeRecent"
+#define GLADE_ACTION_GROUP_PROJECTS_LIST_MENU "GladeProjectsList"
struct _GladeProjectWindowPriv {
/* Application widgets */
@@ -53,17 +54,16 @@ struct _GladeProjectWindowPriv {
GtkUIManager *ui; /* The UIManager */
guint projects_list_menu_ui_id; /* Merge id for projects list menu */
- GtkActionGroup *menu_actions; /* All the static actions */
- GtkActionGroup *project_actions;/* Projects actions */
+ GtkActionGroup *static_actions; /* All the static actions */
+ GtkActionGroup *project_actions;/* All the project actions */
GtkActionGroup *recent_actions; /* Recent projects actions */
+ GtkActionGroup *projects_list_menu_actions;/* Projects list menu actions */
GQueue *recent_projects; /* A GtkAction queue */
gint rp_max; /* Maximun Recent Projects entries */
GtkWindow *palette_window; /* The window that will contain the palette */
GtkWindow *editor_window; /* The window that will contain the editor */
- GtkWidget *toolbar_undo; /* undo item on the toolbar */
- GtkWidget *toolbar_redo; /* redo item on the toolbar */
};
#define WINDOW_TITLE (_("Glade-3 GUI Builder"))
@@ -73,7 +73,7 @@ const gint GLADE_PALETTE_DEFAULT_HEIGH
static gpointer parent_class = NULL;
-static void glade_project_window_refresh_undo_redo (GladeProjectWindow *gpw);
+static void gpw_refresh_undo_redo (GladeProjectWindow *gpw);
static void
gpw_refresh_title (GladeProjectWindow *gpw)
@@ -261,8 +261,73 @@ gpw_refresh_projects_list_item (GladePro
static void
gpw_project_notify_handler_cb (GladeProject *project, GParamSpec *spec, GladeProjectWindow *gpw)
{
- gpw_refresh_title (gpw);
- gpw_refresh_projects_list_item (gpw, project);
+ GtkAction *action;
+
+ if (strcmp (spec->name, "has-unsaved-changes") == 0)
+ {
+ gpw_refresh_title (gpw);
+ gpw_refresh_projects_list_item (gpw, project);
+ }
+ else if (strcmp (spec->name, "read-only") == 0)
+ {
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Save");
+ gtk_action_set_sensitive (action,
+ !glade_project_get_readonly (project));
+ }
+ else if (strcmp (spec->name, "has-selection") == 0)
+ {
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Cut");
+ gtk_action_set_sensitive (action,
+ glade_project_get_has_selection (project));
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Copy");
+ gtk_action_set_sensitive (action,
+ glade_project_get_has_selection (project));
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Delete");
+ gtk_action_set_sensitive (action,
+ glade_project_get_has_selection (project));
+ }
+}
+
+static void
+gpw_clipboard_notify_handler_cb (GladeClipboard *clipboard, GParamSpec *spec, GladeProjectWindow *gpw)
+{
+ GtkAction *action;
+
+ if (strcmp (spec->name, "has-selection") == 0)
+ {
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Paste");
+ gtk_action_set_sensitive (action,
+ glade_clipboard_get_has_selection (clipboard));
+ }
+}
+
+static void
+gpw_set_sensitivity_according_to_project (GladeProjectWindow *gpw, GladeProject *project)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Save");
+ gtk_action_set_sensitive (action,
+ !glade_project_get_readonly (project));
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Cut");
+ gtk_action_set_sensitive (action,
+ glade_project_get_has_selection (project));
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Copy");
+ gtk_action_set_sensitive (action,
+ glade_project_get_has_selection (project));
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Paste");
+ gtk_action_set_sensitive (action,
+ glade_clipboard_get_has_selection
+ (glade_app_get_clipboard (GLADE_APP (gpw))));
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Delete");
+ gtk_action_set_sensitive (action,
+ glade_project_get_has_selection (project));
}
static void
@@ -275,6 +340,8 @@ gpw_projects_list_menu_activate_cb (GtkA
glade_app_set_project (GLADE_APP (gpw), project);
+ gpw_set_sensitivity_according_to_project (gpw, project);
+
gpw_refresh_title (gpw);
}
@@ -291,13 +358,13 @@ gpw_refresh_projects_list_menu (GladePro
gtk_ui_manager_remove_ui (p->ui, p->projects_list_menu_ui_id);
/* Remove all current actions */
- actions = gtk_action_group_list_actions (p->project_actions);
+ actions = gtk_action_group_list_actions (p->projects_list_menu_actions);
for (l = actions; l != NULL; l = l->next)
{
g_signal_handlers_disconnect_by_func
(GTK_ACTION (l->data),
G_CALLBACK (gpw_projects_list_menu_activate_cb), gpw);
- gtk_action_group_remove_action (p->project_actions, GTK_ACTION (l->data));
+ gtk_action_group_remove_action (p->projects_list_menu_actions, GTK_ACTION (l->data));
}
g_list_free (actions);
@@ -329,7 +396,10 @@ gpw_refresh_projects_list_menu (GladePro
group = gtk_radio_action_get_group (action);
- gtk_action_group_add_action (p->project_actions, GTK_ACTION (action));
+ gtk_action_group_add_action (p->projects_list_menu_actions, GTK_ACTION (action));
+
+ if (project == glade_app_get_active_project (GLADE_APP (gpw)))
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
g_signal_connect (action, "activate",
G_CALLBACK (gpw_projects_list_menu_activate_cb),
@@ -341,9 +411,6 @@ gpw_refresh_projects_list_menu (GladePro
GTK_UI_MANAGER_MENUITEM,
FALSE);
- if (project == glade_app_get_active_project (GLADE_APP (gpw)))
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
-
g_object_unref (action);
g_free (action_name);
@@ -675,7 +742,9 @@ gpw_confirm_close_project (GladeProjectW
static void
do_close (GladeProjectWindow *gpw, GladeProject *project)
-{
+{
+ GladeProject *active_project;
+
g_signal_handlers_disconnect_by_func (G_OBJECT (project),
G_CALLBACK (gpw_project_notify_handler_cb),
gpw);
@@ -685,6 +754,12 @@ do_close (GladeProjectWindow *gpw, Glade
gpw_refresh_projects_list_menu (gpw);
gpw_refresh_title (gpw);
+
+ active_project = glade_app_get_active_project (GLADE_APP (gpw));
+ if (active_project != NULL)
+ gpw_set_sensitivity_according_to_project (gpw, active_project);
+ else
+ gtk_action_group_set_sensitive (gpw->priv->project_actions, FALSE);
}
static void
@@ -1213,7 +1288,7 @@ static const gchar *ui_info =
" </toolbar>"
"</ui>\n";
-static GtkActionEntry entries[] = {
+static GtkActionEntry static_entries[] = {
{ "FileMenu", NULL, "_File" },
{ "EditMenu", NULL, "_Edit" },
{ "ViewMenu", NULL, "_View" },
@@ -1231,7 +1306,19 @@ static GtkActionEntry entries[] = {
{ "ClearRecents", GTK_STOCK_CLEAR, "Clear Recent Projects", NULL,
NULL, G_CALLBACK (gpw_recent_project_clear_cb) },
-
+
+ { "Quit", GTK_STOCK_QUIT, "_Quit", "<control>Q",
+ "Quit the program", G_CALLBACK (gpw_quit_cb) },
+
+ /* HelpMenu */
+ { "About", GTK_STOCK_ABOUT, "_About", NULL,
+ "Shows the About Dialog", G_CALLBACK (gpw_about_cb) }
+};
+static guint n_static_entries = G_N_ELEMENTS (static_entries);
+
+static GtkActionEntry project_entries[] = {
+
+ /* FileMenu */
{ "Save", GTK_STOCK_SAVE, "_Save","<control>S",
"Save the current project file", G_CALLBACK (gpw_save_cb) },
@@ -1240,9 +1327,6 @@ static GtkActionEntry entries[] = {
{ "Close", GTK_STOCK_CLOSE, "_Close", "<control>W",
"Close the current project file", G_CALLBACK (gpw_close_cb) },
-
- { "Quit", GTK_STOCK_QUIT, "_Quit", "<control>Q",
- "Quit the program", G_CALLBACK (gpw_quit_cb) },
/* EditMenu */
{ "Undo", GTK_STOCK_UNDO, "_Undo", "<control>Z",
@@ -1261,13 +1345,9 @@ static GtkActionEntry entries[] = {
"Paste the clipboard", G_CALLBACK (gpw_paste_cb) },
{ "Delete", GTK_STOCK_DELETE, "_Delete", "Delete",
- "Delete the selection", G_CALLBACK (gpw_delete_cb) },
-
- /* HelpMenu */
- { "About", GTK_STOCK_ABOUT, "_About", NULL,
- "Shows the About Dialog", G_CALLBACK (gpw_about_cb) }
+ "Delete the selection", G_CALLBACK (gpw_delete_cb) }
};
-static guint n_entries = G_N_ELEMENTS (entries);
+static guint n_project_entries = G_N_ELEMENTS (project_entries);
static GtkToggleActionEntry view_entries[] = {
/* ViewMenu */
@@ -1341,32 +1421,41 @@ gpw_ui_disconnect_proxy_cb (GtkUIManager
}
}
-
static GtkWidget *
gpw_construct_menu (GladeProjectWindow *gpw)
{
GError *error = NULL;
- gpw->priv->menu_actions = gtk_action_group_new (GLADE_ACTION_GROUP_MENU);
- gtk_action_group_add_actions (gpw->priv->menu_actions, entries, n_entries, gpw);
- gtk_action_group_add_toggle_actions (gpw->priv->menu_actions, view_entries,
- n_view_entries, gpw);
+ gpw->priv->static_actions = gtk_action_group_new (GLADE_ACTION_GROUP_STATIC);
+ gtk_action_group_add_actions (gpw->priv->static_actions,
+ static_entries,
+ n_static_entries,
+ gpw);
+ gtk_action_group_add_toggle_actions (gpw->priv->static_actions,
+ view_entries,
+ n_view_entries,
+ gpw);
gpw->priv->project_actions = gtk_action_group_new (GLADE_ACTION_GROUP_PROJECT);
+ gtk_action_group_add_actions (gpw->priv->project_actions,
+ project_entries,
+ n_project_entries,
+ gpw);
+ gpw->priv->projects_list_menu_actions = gtk_action_group_new (GLADE_ACTION_GROUP_PROJECTS_LIST_MENU);
gpw->priv->recent_actions = gtk_action_group_new (GLADE_ACTION_GROUP_RECENT);
gpw->priv->ui = gtk_ui_manager_new ();
g_signal_connect(G_OBJECT(gpw->priv->ui), "connect-proxy",
G_CALLBACK (gpw_ui_connect_proxy_cb), gpw);
-
g_signal_connect(G_OBJECT(gpw->priv->ui), "disconnect-proxy",
G_CALLBACK (gpw_ui_disconnect_proxy_cb), gpw);
- gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->menu_actions, 0);
+ gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->static_actions, 0);
gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->project_actions, 1);
gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->recent_actions, 2);
+ gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->projects_list_menu_actions, 3);
gtk_window_add_accel_group (GTK_WINDOW (gpw->priv->window),
gtk_ui_manager_get_accel_group (gpw->priv->ui));
@@ -1376,7 +1465,7 @@ gpw_construct_menu (GladeProjectWindow *
g_message ("Building menus failed: %s", error->message);
g_error_free (error);
}
-
+
gtk_widget_set_sensitive (gtk_ui_manager_get_widget
(gpw->priv->ui, "/MenuBar/FileMenu/Recents"),
FALSE);
@@ -1384,7 +1473,6 @@ gpw_construct_menu (GladeProjectWindow *
return gtk_ui_manager_get_widget (gpw->priv->ui, "/MenuBar");
}
-
static GtkWidget *
gpw_construct_statusbar (GladeProjectWindow *gpw)
{
@@ -1481,16 +1569,11 @@ glade_project_window_create (GladeProjec
project_view = gpw_create_widget_tree_contents (gpw);
statusbar = gpw_construct_statusbar (gpw);
- gpw->priv->toolbar_undo = gtk_ui_manager_get_widget (gpw->priv->ui, "/ToolBar/Undo");
- gpw->priv->toolbar_redo = gtk_ui_manager_get_widget (gpw->priv->ui, "/ToolBar/Redo");
-
gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), project_view, TRUE, TRUE, 0);
gtk_box_pack_end (GTK_BOX (vbox), statusbar, FALSE, TRUE, 0);
- glade_project_window_refresh_undo_redo (gpw);
-
gpw_recent_project_config_load (gpw);
/* support for opening a file by dragging onto the project window */
@@ -1513,16 +1596,25 @@ glade_project_window_add_project (GladeP
glade_app_add_project (GLADE_APP (gpw), project);
- /* Connect callback handler for notify signal emitted by projects */
+ /* Connect callback handler for notify signals emitted by projects */
g_signal_connect (G_OBJECT (project), "notify::has-unsaved-changes",
G_CALLBACK (gpw_project_notify_handler_cb),
gpw);
+ g_signal_connect (G_OBJECT (project), "notify::has-selection",
+ G_CALLBACK (gpw_project_notify_handler_cb),
+ gpw);
+ g_signal_connect (G_OBJECT (project), "notify::read-only",
+ G_CALLBACK (gpw_project_notify_handler_cb),
+ gpw);
+
+ gpw_set_sensitivity_according_to_project (gpw, project);
- /* Refresh projects list menu */
gpw_refresh_projects_list_menu (gpw);
- /* Refresh window title */
gpw_refresh_title (gpw);
+
+ if (gtk_action_group_get_sensitive (gpw->priv->project_actions) == FALSE)
+ gtk_action_group_set_sensitive (gpw->priv->project_actions, TRUE);
}
void
@@ -1571,77 +1663,70 @@ glade_project_window_open_project (Glade
glade_project_window_add_project (gpw, project);
}
-void
+static void
glade_project_window_change_menu_label (GladeProjectWindow *gpw,
const gchar *path,
- const gchar *prefix,
- const gchar *suffix)
+ const gchar *action_label,
+ const gchar *action_description)
{
- gboolean sensitive = TRUE;
GtkBin *bin;
GtkLabel *label;
gchar *text;
-
- bin = GTK_BIN (gtk_ui_manager_get_widget (gpw->priv->ui, path));
- label = GTK_LABEL (gtk_bin_get_child (bin));
-
- if (prefix == NULL)
- {
- gtk_label_set_text_with_mnemonic (label, suffix);
- return;
- }
- if (suffix == NULL)
- {
- suffix = _("Nothing");
- sensitive = FALSE;
- }
+ g_assert (GLADE_IS_PROJECT_WINDOW (gpw));
+ g_return_if_fail (path != NULL);
+ g_return_if_fail (action_label != NULL);
- text = g_strconcat (prefix, suffix, NULL);
+ bin = GTK_BIN (gtk_ui_manager_get_widget (gpw->priv->ui, path));
+ label = GTK_LABEL (gtk_bin_get_child (bin));
+ if (action_description == NULL)
+ text = g_strdup (action_label);
+ else
+ text = g_strdup_printf ("%s: %s", action_label, action_description);
+
gtk_label_set_text_with_mnemonic (label, text);
- gtk_widget_set_sensitive (GTK_WIDGET (bin), sensitive);
g_free (text);
}
-void
-glade_project_window_refresh_undo_redo (GladeProjectWindow *gpw)
+static void
+gpw_refresh_undo_redo (GladeProjectWindow *gpw)
{
GladeCommand *undo = NULL, *redo = NULL;
GladeProject *project;
GtkAction *action;
- gchar *desc;
+ gchar *tooltip;
- if ((project = glade_app_get_active_project (GLADE_APP (gpw))) != NULL)
+ project = glade_app_get_active_project (GLADE_APP (gpw));
+
+ if (project != NULL)
{
undo = glade_command_next_undo_item (project);
redo = glade_command_next_redo_item (project);
}
- /* Change label in menu */
- glade_project_window_change_menu_label
- (gpw, "/MenuBar/EditMenu/Undo", _("_Undo: "), undo ? undo->description : " ");
+ /* Refresh Undo */
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Undo");
+ gtk_action_set_sensitive (action, undo != NULL);
glade_project_window_change_menu_label
- (gpw, "/MenuBar/EditMenu/Redo", _("_Redo: "), redo ? redo->description : " ");
+ (gpw, "/MenuBar/EditMenu/Undo", _("_Undo"), undo ? undo->description : NULL);
+ tooltip = g_strdup_printf (_("Undo: %s"), undo ? undo->description : _("the last action"));
+ g_object_set (action, "tooltip", tooltip, NULL);
+ g_free (tooltip);
- /* Change tooltips on the toolbar */
- desc = g_strdup_printf (_("Undo: %s"), undo ? undo->description : _("the last action"));
- action = gtk_ui_manager_get_action (gpw->priv->ui, "/ToolBar/Undo");
- g_object_set (G_OBJECT (action), "tooltip", desc, NULL);
- g_free (desc);
-
- desc = g_strdup_printf (_("Redo: %s"), redo ? redo->description : _("the last action"));
- action = gtk_ui_manager_get_action (gpw->priv->ui, "/ToolBar/Redo");
- g_object_set (G_OBJECT (action), "tooltip", desc, NULL);
- g_free (desc);
-
- /* Set sensitivity on the toolbar */
- gtk_widget_set_sensitive (gpw->priv->toolbar_undo, undo != NULL);
- gtk_widget_set_sensitive (gpw->priv->toolbar_redo, redo != NULL);
+ /* Refresh Redo */
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "Redo");
+ gtk_action_set_sensitive (action, redo != NULL);
+
+ glade_project_window_change_menu_label
+ (gpw, "/MenuBar/EditMenu/Redo", _("_Redo"), redo ? redo->description : NULL);
+ tooltip = g_strdup_printf (_("Redo: %s"), redo ? redo->description : _("the last action"));
+ g_object_set (action, "tooltip", tooltip, NULL);
+ g_free (tooltip);
}
static void
@@ -1652,7 +1737,7 @@ glade_project_window_update_ui (GladeApp
/* Chain Up */
GLADE_APP_CLASS (parent_class)->update_ui_signal (app);
- glade_project_window_refresh_undo_redo (gpw);
+ gpw_refresh_undo_redo (gpw);
}
void
@@ -1749,6 +1834,11 @@ glade_project_window_new (void)
gtk_window_add_accel_group(gpw->priv->palette_window, accel_group);
gtk_window_add_accel_group(gpw->priv->editor_window, accel_group);
gtk_window_add_accel_group(GTK_WINDOW (glade_app_get_clipboard_view (GLADE_APP (gpw))), accel_group);
+
+ /* Connect callback handler for notify signals emitted by clipboard */
+ g_signal_connect (G_OBJECT (glade_app_get_clipboard (GLADE_APP (gpw))), "notify::has-selection",
+ G_CALLBACK (gpw_clipboard_notify_handler_cb),
+ gpw);
return gpw;
}
Index: src/glade-clipboard.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-clipboard.c,v
retrieving revision 1.19
diff -u -p -r1.19 glade-clipboard.c
--- src/glade-clipboard.c 10 Feb 2006 03:41:21 -0000 1.19
+++ src/glade-clipboard.c 9 Apr 2006 12:15:08 -0000
@@ -31,10 +31,47 @@
#include "glade-placeholder.h"
#include "glade-project.h"
+enum
+{
+ PROP_0,
+ PROP_HAS_SELECTION
+};
+
+static void
+glade_project_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GladeClipboard *clipboard = GLADE_CLIPBOARD (object);
+
+ switch (prop_id)
+ {
+ case PROP_HAS_SELECTION:
+ g_value_set_boolean (value, clipboard->has_selection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
glade_clipboard_class_init (GladeClipboardClass *klass)
{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = glade_project_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_HAS_SELECTION,
+ g_param_spec_boolean ("has-selection",
+ "Has Selection",
+ "Whether clipboard has a selection of items to paste",
+ FALSE,
+ G_PARAM_READABLE));
}
static void
@@ -43,6 +80,7 @@ glade_clipboard_init (GladeClipboard *cl
clipboard->widgets = NULL;
clipboard->view = NULL;
clipboard->selection = NULL;
+ clipboard->has_selection = FALSE;
}
GType
@@ -70,6 +108,34 @@ glade_clipboard_get_type (void)
return type;
}
+static void
+glade_clipboard_set_has_selection (GladeClipboard *clipboard, gboolean has_selection)
+{
+ g_assert (GLADE_IS_CLIPBOARD (clipboard));
+
+ if (clipboard->has_selection != has_selection)
+ {
+ clipboard->has_selection = has_selection;
+ g_object_notify (G_OBJECT (clipboard), "has-selection");
+ }
+
+}
+
+/**
+ * glade_clipboard_get_has_selection:
+ * @clipboard: a #GladeClipboard
+ *
+ * Returns: TRUE if this clipboard has selected items to paste.
+ */
+gboolean
+glade_clipboard_get_has_selection (GladeClipboard *clipboard)
+{
+ g_assert (GLADE_IS_CLIPBOARD (clipboard));
+
+ return clipboard->has_selection;
+}
+
+
/**
* glade_clipboard_new:
*
@@ -176,6 +242,8 @@ glade_clipboard_selection_add (GladeClip
g_return_if_fail (GLADE_IS_WIDGET (widget));
clipboard->selection =
g_list_prepend (clipboard->selection, widget);
+
+ glade_clipboard_set_has_selection (clipboard, TRUE);
}
void
@@ -186,6 +254,9 @@ glade_clipboard_selection_remove (GladeC
g_return_if_fail (GLADE_IS_WIDGET (widget));
clipboard->selection =
g_list_remove (clipboard->selection, widget);
+
+ if (g_list_length (clipboard->selection) == 0)
+ glade_clipboard_set_has_selection (clipboard, FALSE);
}
void
@@ -194,5 +265,6 @@ glade_clipboard_selection_clear (GladeCl
g_return_if_fail (GLADE_IS_CLIPBOARD (clipboard));
clipboard->selection =
(g_list_free (clipboard->selection), NULL);
-}
+ glade_clipboard_set_has_selection (clipboard, FALSE);
+}
Index: src/glade-clipboard.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-clipboard.h,v
retrieving revision 1.9
diff -u -p -r1.9 glade-clipboard.h
--- src/glade-clipboard.h 7 Feb 2006 05:24:07 -0000 1.9
+++ src/glade-clipboard.h 9 Apr 2006 12:15:08 -0000
@@ -18,6 +18,7 @@ struct _GladeClipboard {
GList *widgets; /* A list of GladeWidget's on the clipboard */
GList *selection; /* Selection list of GladeWidget's */
+ gboolean has_selection; /* TRUE if clipboard has selection */
GtkWidget *view; /* see glade-clipboard-view.c */
};
@@ -46,6 +47,8 @@ void glade_clipboard_selectio
GladeWidget *widget);
LIBGLADEUI_API
void glade_clipboard_selection_clear (GladeClipboard *clipboard);
+LIBGLADEUI_API
+gboolean glade_clipboard_get_has_selection (GladeClipboard *clipboard);
G_END_DECLS
_______________________________________________
Glade-devel maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/glade-devel