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 <glib/gi18n.h>
35 #include <string.h>
36
37 #include <api/na-core-utils.h>
38 #include <api/na-object-api.h>
39
40 #include "base-window.h"
41 #include "base-gtk-utils.h"
42 #include "nact-application.h"
43 #include "nact-main-tab.h"
44 #include "nact-match-list.h"
45 #include "nact-ifolders-tab.h"
46
47 /* private interface data
48 */
49 struct _NactIFoldersTabInterfacePrivate {
50 void *empty; /* so that gcc -pedantic is happy */
51 };
52
53 /* the identifier of this notebook page in the Match dialog
54 */
55 #define ITAB_NAME "folders"
56
57 static guint st_initializations = 0; /* interface initialization count */
58
59 static GType register_type( void );
60 static void interface_base_init( NactIFoldersTabInterface *klass );
61 static void interface_base_finalize( NactIFoldersTabInterface *klass );
62
63 static void on_base_initialize_gtk( NactIFoldersTab *instance, GtkWindow *toplevel, gpointer user_data );
64 static void on_base_initialize_window( NactIFoldersTab *instance, gpointer user_data );
65
66 static void on_main_selection_changed( NactIFoldersTab *instance, GList *selected_items, gpointer user_data );
67
68 static void on_browse_folder_clicked( GtkButton *button, BaseWindow *window );
69 static GSList *get_folders( void *context );
70 static void set_folders( void *context, GSList *filters );
71
72 static void on_instance_finalized( gpointer user_data, NactIFoldersTab *instance );
73
74 GType
nact_ifolders_tab_get_type(void)75 nact_ifolders_tab_get_type( void )
76 {
77 static GType iface_type = 0;
78
79 if( !iface_type ){
80 iface_type = register_type();
81 }
82
83 return( iface_type );
84 }
85
86 static GType
register_type(void)87 register_type( void )
88 {
89 static const gchar *thisfn = "nact_ifolders_tab_register_type";
90 GType type;
91
92 static const GTypeInfo info = {
93 sizeof( NactIFoldersTabInterface ),
94 ( GBaseInitFunc ) interface_base_init,
95 ( GBaseFinalizeFunc ) interface_base_finalize,
96 NULL,
97 NULL,
98 NULL,
99 0,
100 0,
101 NULL
102 };
103
104 g_debug( "%s", thisfn );
105
106 type = g_type_register_static( G_TYPE_INTERFACE, "NactIFoldersTab", &info, 0 );
107
108 g_type_interface_add_prerequisite( type, BASE_TYPE_WINDOW );
109
110 return( type );
111 }
112
113 static void
interface_base_init(NactIFoldersTabInterface * klass)114 interface_base_init( NactIFoldersTabInterface *klass )
115 {
116 static const gchar *thisfn = "nact_ifolders_tab_interface_base_init";
117
118 if( !st_initializations ){
119
120 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
121
122 klass->private = g_new0( NactIFoldersTabInterfacePrivate, 1 );
123 }
124
125 st_initializations += 1;
126 }
127
128 static void
interface_base_finalize(NactIFoldersTabInterface * klass)129 interface_base_finalize( NactIFoldersTabInterface *klass )
130 {
131 static const gchar *thisfn = "nact_ifolders_tab_interface_base_finalize";
132
133 st_initializations -= 1;
134
135 if( !st_initializations ){
136
137 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
138
139 g_free( klass->private );
140 }
141 }
142
143 /**
144 * nact_ifolders_tab_init:
145 * @instance: this #NactIFoldersTab instance.
146 *
147 * Initialize the interface
148 * Connect to #BaseWindow signals
149 */
150 void
nact_ifolders_tab_init(NactIFoldersTab * instance)151 nact_ifolders_tab_init( NactIFoldersTab *instance )
152 {
153 static const gchar *thisfn = "nact_ifolders_tab_init";
154
155 g_return_if_fail( NACT_IS_IFOLDERS_TAB( instance ));
156
157 g_debug( "%s: instance=%p (%s)",
158 thisfn,
159 ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
160
161 base_window_signal_connect(
162 BASE_WINDOW( instance ),
163 G_OBJECT( instance ),
164 BASE_SIGNAL_INITIALIZE_GTK,
165 G_CALLBACK( on_base_initialize_gtk ));
166
167 base_window_signal_connect(
168 BASE_WINDOW( instance ),
169 G_OBJECT( instance ),
170 BASE_SIGNAL_INITIALIZE_WINDOW,
171 G_CALLBACK( on_base_initialize_window ));
172
173 nact_main_tab_init( NACT_MAIN_WINDOW( instance ), TAB_FOLDERS );
174
175 g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
176 }
177
178 static void
on_base_initialize_gtk(NactIFoldersTab * instance,GtkWindow * toplevel,void * user_data)179 on_base_initialize_gtk( NactIFoldersTab *instance, GtkWindow *toplevel, void *user_data )
180 {
181 static const gchar *thisfn = "nact_ifolders_tab_on_base_initialize_gtk";
182
183 g_return_if_fail( NACT_IS_IFOLDERS_TAB( instance ));
184
185 g_debug( "%s: instance=%p (%s), toplevel=%p, user_data=%p",
186 thisfn,
187 ( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
188 ( void * ) toplevel,
189 ( void * ) user_data );
190
191 nact_match_list_init_with_args(
192 BASE_WINDOW( instance ),
193 ITAB_NAME,
194 TAB_FOLDERS,
195 base_window_get_widget( BASE_WINDOW( instance ), "FoldersTreeView" ),
196 base_window_get_widget( BASE_WINDOW( instance ), "AddFolderButton" ),
197 base_window_get_widget( BASE_WINDOW( instance ), "RemoveFolderButton" ),
198 ( pget_filters ) get_folders,
199 ( pset_filters ) set_folders,
200 NULL,
201 NULL,
202 MATCH_LIST_MUST_MATCH_ONE_OF,
203 _( "Folder filter" ),
204 TRUE );
205 }
206
207 static void
on_base_initialize_window(NactIFoldersTab * instance,void * user_data)208 on_base_initialize_window( NactIFoldersTab *instance, void *user_data )
209 {
210 static const gchar *thisfn = "nact_ifolders_tab_on_base_initialize_window";
211 GtkWidget *button;
212
213 g_return_if_fail( NACT_IS_IFOLDERS_TAB( instance ));
214
215 g_debug( "%s: instance=%p (%s), user_data=%p",
216 thisfn,
217 ( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
218 ( void * ) user_data );
219
220 base_window_signal_connect(
221 BASE_WINDOW( instance ),
222 G_OBJECT( instance ),
223 MAIN_SIGNAL_SELECTION_CHANGED,
224 G_CALLBACK( on_main_selection_changed ));
225
226 button = base_window_get_widget( BASE_WINDOW( instance ), "FolderBrowseButton" );
227 base_window_signal_connect(
228 BASE_WINDOW( instance ),
229 G_OBJECT( button ),
230 "clicked",
231 G_CALLBACK( on_browse_folder_clicked ));
232 }
233
234 static void
on_main_selection_changed(NactIFoldersTab * instance,GList * selected_items,gpointer user_data)235 on_main_selection_changed( NactIFoldersTab *instance, GList *selected_items, gpointer user_data )
236 {
237 NAIContext *context;
238 gboolean editable;
239 gboolean enable_tab;
240 GtkWidget *button;
241
242 g_object_get( G_OBJECT( instance ),
243 MAIN_PROP_CONTEXT, &context, MAIN_PROP_EDITABLE, &editable,
244 NULL );
245
246 enable_tab = ( context != NULL );
247 nact_main_tab_enable_page( NACT_MAIN_WINDOW( instance ), TAB_FOLDERS, enable_tab );
248
249 button = base_window_get_widget( BASE_WINDOW( instance ), "FolderBrowseButton" );
250 base_gtk_utils_set_editable( G_OBJECT( button ), editable );
251 }
252
253 static void
on_browse_folder_clicked(GtkButton * button,BaseWindow * window)254 on_browse_folder_clicked( GtkButton *button, BaseWindow *window )
255 {
256 #if 0
257 /* this is the code I sent to gtk-app-devel list
258 * to know why one is not able to just enter '/' in the location entry
259 */
260 GtkWidget *dialog;
261 gchar *path;
262
263 dialog = gtk_file_chooser_dialog_new( _( "Select a folder" ),
264 NULL,
265 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
266 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
267 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
268 NULL );
269
270 gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( dialog ), "/" );
271
272 if( gtk_dialog_run( GTK_DIALOG( dialog )) == GTK_RESPONSE_ACCEPT ){
273 path = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ));
274 g_debug( "nact_ifolders_tab_on_add_folder_clicked: path=%s", path );
275 g_free( path );
276 }
277
278 gtk_widget_destroy( dialog );
279 #endif
280
281 gchar *uri, *path;
282 GtkWindow *toplevel;
283 GtkWidget *dialog;
284
285 uri = NULL;
286 toplevel = base_window_get_gtk_toplevel( window );
287
288 /* i18n: title of the FileChoose dialog when selecting an URI which
289 * will be compare to Nautilus 'current_folder'
290 */
291 dialog = gtk_file_chooser_dialog_new( _( "Select a folder" ),
292 toplevel,
293 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
294 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
295 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
296 NULL );
297
298 base_gtk_utils_restore_window_position( window, NA_IPREFS_FOLDER_CHOOSER_WSP );
299
300 uri = na_settings_get_string( NA_IPREFS_FOLDER_CHOOSER_URI, NULL, NULL );
301 if( uri && g_utf8_strlen( uri, -1 )){
302 gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( dialog ), uri );
303 }
304 g_free( uri );
305
306 if( gtk_dialog_run( GTK_DIALOG( dialog )) == GTK_RESPONSE_ACCEPT ){
307 uri = gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( dialog ));
308 na_settings_set_string( NA_IPREFS_FOLDER_CHOOSER_URI, uri );
309
310 path = g_filename_from_uri( uri, NULL, NULL );
311 nact_match_list_insert_row( window, ITAB_NAME, path, FALSE, FALSE );
312 g_free( path );
313
314 g_free( uri );
315 }
316
317 base_gtk_utils_save_window_position( window, NA_IPREFS_FOLDER_CHOOSER_WSP );
318
319 gtk_widget_destroy( dialog );
320 }
321
322 static GSList *
get_folders(void * context)323 get_folders( void *context )
324 {
325 return( na_object_get_folders( context ));
326 }
327
328 static void
set_folders(void * context,GSList * filters)329 set_folders( void *context, GSList *filters )
330 {
331 na_object_set_folders( context, filters );
332 }
333
334 static void
on_instance_finalized(gpointer user_data,NactIFoldersTab * instance)335 on_instance_finalized( gpointer user_data, NactIFoldersTab *instance )
336 {
337 static const gchar *thisfn = "nact_ifolders_tab_on_instance_finalized";
338
339 g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
340 }
341