1 /*
2  * Nautilus-Actions
3  * A Nautilus extension which offers configurable context menu actions.
4  *
5  * Copyright (C) 2005 The GNOME Foundation
6  * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7  * Copyright (C) 2009-2014 Pierre Wieser and others (see AUTHORS)
8  *
9  * Nautilus-Actions is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * Nautilus-Actions is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Nautilus-Actions; see the file COPYING. If not, see
21  * <http://www.gnu.org/licenses/>.
22  *
23  * Authors:
24  *   Frederic Ruaudel <grumz@grumz.net>
25  *   Rodrigo Moya <rodrigo@gnome-db.org>
26  *   Pierre Wieser <pwieser@trychlos.org>
27  *   ... and many others (see AUTHORS)
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <core/na-io-provider.h>
35 
36 #include "base-gtk-utils.h"
37 #include "nact-main-statusbar.h"
38 
39 typedef struct {
40 	guint         event_source_id;
41 	guint         context_id;
42 	GtkStatusbar *bar;
43 }
44 	StatusbarTimeoutDisplayStruct;
45 
46 #define LOCKED_IMAGE					PKGUIDIR "/locked.png"
47 
48 static GtkStatusbar *get_statusbar( const NactMainWindow *window );
49 static gboolean      display_timeout( StatusbarTimeoutDisplayStruct *stds );
50 static void          display_timeout_free( StatusbarTimeoutDisplayStruct *stds );
51 
52 /**
53  * nact_main_statusbar_initialize_gtk_toplevel:
54  * @window: the #NactMainWindow.
55  *
56  * Initial loading of the UI.
57  */
58 void
nact_main_statusbar_initialize_gtk_toplevel(NactMainWindow * window)59 nact_main_statusbar_initialize_gtk_toplevel( NactMainWindow *window )
60 {
61 	static const gchar *thisfn = "nact_main_statusbar_initialize_gtk_toplevel";
62 	gint width, height;
63 	GtkStatusbar *bar;
64 	GtkFrame *frame;
65 /* gtk_widget_size_request() is deprecated since Gtk+ 3.0
66  * see http://library.gnome.org/devel/gtk/unstable/GtkWidget.html#gtk-widget-render-icon
67  * and http://git.gnome.org/browse/gtk+/commit/?id=07eeae15825403037b7df139acf9bfa104d5559d
68  */
69 #if GTK_CHECK_VERSION( 2, 91, 7 )
70 	GtkRequisition minimal_size, natural_size;
71 #else
72 	GtkRequisition requisition;
73 #endif
74 
75 	g_debug( "%s: window=%p", thisfn, ( void * ) window );
76 
77 	gtk_icon_size_lookup( GTK_ICON_SIZE_MENU, &width, &height );
78 
79 	bar = get_statusbar( window );
80 	frame = GTK_FRAME( base_window_get_widget( BASE_WINDOW( window ), "ActionLockedFrame" ));
81 
82 #if GTK_CHECK_VERSION( 2, 91, 7 )
83 	gtk_widget_get_preferred_size( GTK_WIDGET( bar ), &minimal_size, &natural_size );
84 	gtk_widget_set_size_request( GTK_WIDGET( bar ), natural_size.width, height+8 );
85 #else
86 	gtk_widget_size_request( GTK_WIDGET( bar ), &requisition );
87 	gtk_widget_set_size_request( GTK_WIDGET( bar ), requisition.width, height+8 );
88 #endif
89 
90 	gtk_widget_set_size_request( GTK_WIDGET( frame ), width+4, height+4 );
91 	gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
92 }
93 
94 /**
95  * nact_main_statusbar_display_status:
96  * @window: the #NactMainWindow instance.
97  * @context: the context to be displayed.
98  * @status: the message.
99  *
100  * Push a message.
101  */
102 void
nact_main_statusbar_display_status(NactMainWindow * window,const gchar * context,const gchar * status)103 nact_main_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status )
104 {
105 	static const gchar *thisfn = "nact_main_statusbar_display_status";
106 	GtkStatusbar *bar;
107 
108 	g_debug( "%s: window=%p, context=%s, status=%s", thisfn, ( void * ) window, context, status );
109 
110 	if( !status || !g_utf8_strlen( status, -1 )){
111 		return;
112 	}
113 
114 	bar = get_statusbar( window );
115 
116 	if( bar ){
117 		guint context_id = gtk_statusbar_get_context_id( bar, context );
118 		gtk_statusbar_push( bar, context_id, status );
119 	}
120 }
121 
122 /**
123  * nact_main_statusbar_display_with_timeout:
124  * @window: the #NactMainWindow instance.
125  * @context: the context to be displayed.
126  * @status: the message.
127  *
128  * Push a message.
129  * Automatically pop it after a timeout.
130  * The timeout is not suspended when another message is pushed onto the
131  * previous one.
132  */
133 void
nact_main_statusbar_display_with_timeout(NactMainWindow * window,const gchar * context,const gchar * status)134 nact_main_statusbar_display_with_timeout( NactMainWindow *window, const gchar *context, const gchar *status )
135 {
136 	static const gchar *thisfn = "nact_main_statusbar_display_with_timeout";
137 	GtkStatusbar *bar;
138 	StatusbarTimeoutDisplayStruct *stds;
139 
140 	g_debug( "%s: window=%p, context=%s, status=%s", thisfn, ( void * ) window, context, status );
141 
142 	if( !status || !g_utf8_strlen( status, -1 )){
143 		return;
144 	}
145 
146 	bar = get_statusbar( window );
147 
148 	if( bar ){
149 		guint context_id = gtk_statusbar_get_context_id( bar, context );
150 		gtk_statusbar_push( bar, context_id, status );
151 
152 		stds = g_new0( StatusbarTimeoutDisplayStruct, 1 );
153 		stds->context_id = context_id;
154 		stds->bar = bar;
155 		stds->event_source_id = g_timeout_add_seconds_full(
156 				G_PRIORITY_DEFAULT,
157 				10,
158 				( GSourceFunc ) display_timeout,
159 				stds,
160 				( GDestroyNotify ) display_timeout_free );
161 	}
162 }
163 
164 /**
165  * nact_main_statusbar_hide_status:
166  * @window: the #NactMainWindow instance.
167  * @context: the context to be hidden.
168  *
169  * Hide the specified context.
170  */
171 void
nact_main_statusbar_hide_status(NactMainWindow * window,const gchar * context)172 nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context )
173 {
174 	GtkStatusbar *bar;
175 
176 	bar = get_statusbar( window );
177 
178 	if( bar ){
179 		guint context_id = gtk_statusbar_get_context_id( bar, context );
180 		gtk_statusbar_pop( bar, context_id );
181 	}
182 }
183 
184 /**
185  * nact_main_statusbar_set_locked:
186  * @window: the #NactMainWindow instance.
187  * @provider: whether the current provider is locked (read-only).
188  * @item: whether the current item is locked (read-only).
189  *
190  * Displays the writability status of the current item as an image.
191  * Installs the corresponding tooltip.
192  */
193 void
nact_main_statusbar_set_locked(NactMainWindow * window,gboolean readonly,gint reason)194 nact_main_statusbar_set_locked( NactMainWindow *window, gboolean readonly, gint reason )
195 {
196 	static const gchar *thisfn = "nact_main_statusbar_set_locked";
197 	GtkStatusbar *bar;
198 	GtkFrame *frame;
199 	GtkImage *image;
200 	gchar *tooltip;
201 	gboolean set_pixbuf;
202 
203 	g_debug( "%s: window=%p, readonly=%s, reason=%d", thisfn, ( void * ) window, readonly ? "True":"False", reason );
204 
205 	set_pixbuf = TRUE;
206 	bar = get_statusbar( window );
207 	frame = GTK_FRAME( base_window_get_widget( BASE_WINDOW( window ), "ActionLockedFrame" ));
208 	image = GTK_IMAGE( base_window_get_widget( BASE_WINDOW( window ), "ActionLockedImage" ));
209 
210 	if( bar && frame && image ){
211 
212 		tooltip = g_strdup( "" );
213 
214 		if( readonly ){
215 			gtk_image_set_from_file( image, LOCKED_IMAGE );
216 			set_pixbuf = FALSE;
217 			g_free( tooltip );
218 			tooltip = na_io_provider_get_readonly_tooltip( reason );
219 		}
220 
221 		gtk_widget_set_tooltip_text( GTK_WIDGET( image ), tooltip );
222 		g_free( tooltip );
223 	}
224 
225 	if( set_pixbuf ){
226 		base_gtk_utils_render( NULL, image, GTK_ICON_SIZE_MENU );
227 	}
228 }
229 
230 /*
231  * Returns the status bar widget
232  */
233 static GtkStatusbar *
get_statusbar(const NactMainWindow * window)234 get_statusbar( const NactMainWindow *window )
235 {
236 	GtkWidget *statusbar;
237 
238 	statusbar = base_window_get_widget( BASE_WINDOW( window ), "MainStatusbar" );
239 
240 	return( GTK_STATUSBAR( statusbar ));
241 }
242 
243 static gboolean
display_timeout(StatusbarTimeoutDisplayStruct * stds)244 display_timeout( StatusbarTimeoutDisplayStruct *stds )
245 {
246 	gboolean keep_source = FALSE;
247 
248 	gtk_statusbar_pop( stds->bar, stds->context_id );
249 
250 	return( keep_source );
251 }
252 
253 static void
display_timeout_free(StatusbarTimeoutDisplayStruct * stds)254 display_timeout_free( StatusbarTimeoutDisplayStruct *stds )
255 {
256 	g_debug( "nact_main_statusbar_display_timeout_free: stds=%p", ( void * ) stds );
257 
258 	g_free( stds );
259 }
260