1 /* -*- Mode: C; indent-spaces-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * plugin.c
4 * Copyright (C) 2012 Carl-Anton Ingmarsson <carlantoni@src.gnome.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <config.h>
22
23 #include "plugin.h"
24
25 #include <libanjuta/anjuta-debug.h>
26 #include <libanjuta/interfaces/ianjuta-file.h>
27 #include <libanjuta/interfaces/ianjuta-file-loader.h>
28
29 #include <signal.h>
30
31 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-quick-open.xml"
32
33 struct _QuickOpenPluginClass
34 {
35 AnjutaPluginClass parent_class;
36 };
37
38 static void
on_dialog_response(GtkDialog * dialog,gint response_id,gpointer user_data)39 on_dialog_response(GtkDialog* dialog, gint response_id, gpointer user_data)
40 {
41 QuickOpenPlugin* self = user_data;
42
43 gtk_widget_hide(GTK_WIDGET(dialog));
44
45 if (response_id == GTK_RESPONSE_ACCEPT)
46 {
47 GObject* object;
48
49 object = quick_open_dialog_get_selected_object(self->dialog);
50 if (!object)
51 return;
52
53 if (IANJUTA_IS_DOCUMENT(object))
54 {
55 ianjuta_document_manager_set_current_document(self->docman,
56 IANJUTA_DOCUMENT(object), NULL);
57 }
58 else if (G_IS_FILE(object))
59 {
60 IAnjutaFileLoader* loader;
61
62 loader = anjuta_shell_get_interface (ANJUTA_PLUGIN (self)->shell,
63 IAnjutaFileLoader, NULL);
64 g_return_if_fail (loader != NULL);
65
66 ianjuta_file_loader_load (loader, G_FILE(object), FALSE, NULL);
67 }
68
69 g_object_unref(object);
70 }
71 }
72
73 static void
on_quick_open_activate(GtkAction * action,QuickOpenPlugin * self)74 on_quick_open_activate(GtkAction *action, QuickOpenPlugin *self)
75 {
76 gtk_widget_show(GTK_WIDGET(self->dialog));
77 }
78
79 static void
project_node_foreach_func(AnjutaProjectNode * node,gpointer data)80 project_node_foreach_func(AnjutaProjectNode *node, gpointer data)
81 {
82 GSList** project_files = data;
83 AnjutaProjectNodeType type;
84
85 type = anjuta_project_node_get_node_type(node);
86
87 if (type == ANJUTA_PROJECT_SOURCE)
88 {
89 GFile* file;
90
91 file = anjuta_project_node_get_file(node);
92 *project_files = g_slist_prepend(*project_files, file);
93 }
94 }
95
96 static void
quick_open_plugin_load_project_files(QuickOpenPlugin * self,IAnjutaProject * project)97 quick_open_plugin_load_project_files(QuickOpenPlugin* self, IAnjutaProject* project)
98 {
99 AnjutaProjectNode* root;
100 GSList* project_files = NULL;
101
102 root = ianjuta_project_get_root (project, NULL);
103
104 anjuta_project_node_foreach(root, G_POST_ORDER, project_node_foreach_func, &project_files);
105 quick_open_dialog_add_project_files(self->dialog, project_files);
106 g_slist_free(project_files);
107 }
108
109 static void
on_project_loaded(IAnjutaProjectManager * project_manager,GError * error,gpointer user_data)110 on_project_loaded(IAnjutaProjectManager *project_manager, GError *error, gpointer user_data)
111 {
112 QuickOpenPlugin* self = user_data;
113
114 IAnjutaProject* project;
115
116 project = ianjuta_project_manager_get_current_project(project_manager, NULL);
117 quick_open_plugin_load_project_files(self, project);
118 }
119
120 static void
quick_open_plugin_project_added(QuickOpenPlugin * self,IAnjutaProject * project)121 quick_open_plugin_project_added(QuickOpenPlugin* self, IAnjutaProject* project)
122 {
123 AnjutaProjectNode* root;
124 GFile* project_root;
125
126 root = ianjuta_project_get_root(project, NULL);
127 project_root = anjuta_project_node_get_file(root);
128 quick_open_dialog_set_project_root(self->dialog, project_root);
129
130 if (ianjuta_project_is_loaded(project, NULL))
131 quick_open_plugin_load_project_files(self, project);
132 }
133
134 static void
current_project_added(AnjutaPlugin * plugin,const char * name,const GValue * value,gpointer user_data)135 current_project_added(AnjutaPlugin *plugin, const char *name, const GValue *value, gpointer user_data)
136 {
137 QuickOpenPlugin* self = ANJUTA_PLUGIN_QUICK_OPEN(plugin);
138
139 IAnjutaProject* project = g_value_get_object(value);
140 quick_open_plugin_project_added(self, project);
141 }
142
143 static void
current_project_removed(AnjutaPlugin * plugin,const char * name,gpointer user_data)144 current_project_removed(AnjutaPlugin *plugin, const char *name, gpointer user_data)
145 {
146 QuickOpenPlugin* self = ANJUTA_PLUGIN_QUICK_OPEN(plugin);
147
148 quick_open_dialog_set_project_root(self->dialog, NULL);
149 }
150
151 static void
quick_open_plugin_setup_project_handling(QuickOpenPlugin * self)152 quick_open_plugin_setup_project_handling(QuickOpenPlugin* self)
153 {
154 IAnjutaProject* project;
155
156 self->project_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN(self)->shell,
157 IAnjutaProjectManager, NULL);
158 g_return_if_fail(self->project_manager);
159
160 g_object_add_weak_pointer(G_OBJECT(self->project_manager), (void**)&self->project_manager);
161
162 /* Connect to project manager events. */
163 self->project_watch_id = anjuta_plugin_add_watch(ANJUTA_PLUGIN(self),
164 IANJUTA_PROJECT_MANAGER_CURRENT_PROJECT,
165 current_project_added, current_project_removed, self);
166
167 g_signal_connect(self->project_manager, "project-loaded",
168 G_CALLBACK (on_project_loaded), self);
169
170 project = ianjuta_project_manager_get_current_project (self->project_manager, NULL);
171 if (project)
172 quick_open_plugin_project_added(self, project);
173 }
174
175 static void
on_document_removed(IAnjutaDocumentManager * docman,IAnjutaDocument * doc,gpointer user_data)176 on_document_removed(IAnjutaDocumentManager* docman, IAnjutaDocument* doc, gpointer user_data)
177 {
178 QuickOpenPlugin* self = user_data;
179
180 quick_open_dialog_remove_document(self->dialog, doc);
181 }
182
183 static void
on_document_added(IAnjutaDocumentManager * docman,IAnjutaDocument * doc,gpointer user_data)184 on_document_added(IAnjutaDocumentManager* docman, IAnjutaDocument* doc, gpointer user_data)
185 {
186 QuickOpenPlugin* self = user_data;
187
188 quick_open_dialog_add_document(self->dialog, doc);
189 }
190
191 static void
quick_open_plugin_setup_document_handling(QuickOpenPlugin * self)192 quick_open_plugin_setup_document_handling(QuickOpenPlugin* self)
193 {
194 GList* documents, *l;
195
196 self->docman = anjuta_shell_get_interface(ANJUTA_PLUGIN(self)->shell,
197 IAnjutaDocumentManager, NULL);
198 g_return_if_fail(self->docman);
199
200 g_object_add_weak_pointer(G_OBJECT(self->docman), (void**)&self->docman);
201
202 documents = ianjuta_document_manager_get_doc_widgets(self->docman, NULL);
203 for (l = documents; l; l = l->next)
204 {
205 IAnjutaDocument* doc = IANJUTA_DOCUMENT(l->data);
206 quick_open_dialog_add_document(self->dialog, doc);
207 }
208 g_list_free(documents);
209
210 g_signal_connect(self->docman, "document-added", G_CALLBACK(on_document_added), self);
211 g_signal_connect(self->docman, "document-removed", G_CALLBACK(on_document_removed), self);
212 }
213
214 /* Actions table
215 *---------------------------------------------------------------------------*/
216
217 static GtkActionEntry actions_quick_open[] = {
218 {
219 "ActionQuickOpen",
220 GTK_STOCK_OPEN,
221 N_("Quick open"),
222 "<Control><Alt>o",
223 N_("Quickly open a file in the current project."),
224 G_CALLBACK(on_quick_open_activate)
225 }
226 };
227
228 /* AnjutaPlugin functions
229 *---------------------------------------------------------------------------*/
230
231 static gboolean
quick_open_plugin_activate(AnjutaPlugin * plugin)232 quick_open_plugin_activate(AnjutaPlugin *plugin)
233 {
234 QuickOpenPlugin *self = ANJUTA_PLUGIN_QUICK_OPEN(plugin);
235
236 AnjutaUI* ui;
237
238 DEBUG_PRINT("%s", "Quick Open Plugin: Activating plugin…");
239
240 /* Add actions */
241 ui = anjuta_shell_get_ui(plugin->shell, NULL);
242 self->action_group = anjuta_ui_add_action_group_entries(ui,
243 "ActionsQuickOpen", _("Quick open operations"),
244 actions_quick_open, G_N_ELEMENTS(actions_quick_open),
245 GETTEXT_PACKAGE, TRUE, self);
246
247 self->uiid = anjuta_ui_merge(ui, UI_FILE);
248
249
250 /* Create the dialog. */
251 self->dialog = quick_open_dialog_new();
252 gtk_window_set_transient_for(GTK_WINDOW(self->dialog), GTK_WINDOW(plugin->shell));
253
254 g_signal_connect(self->dialog, "delete-event",
255 G_CALLBACK(gtk_widget_hide_on_delete), NULL);
256 g_signal_connect(self->dialog, "response",
257 G_CALLBACK(on_dialog_response), self);
258
259 quick_open_plugin_setup_project_handling(self);
260 quick_open_plugin_setup_document_handling(self);
261
262
263 return TRUE;
264 }
265
266 static gboolean
quick_open_plugin_deactivate(AnjutaPlugin * plugin)267 quick_open_plugin_deactivate(AnjutaPlugin *plugin)
268 {
269 QuickOpenPlugin *self = ANJUTA_PLUGIN_QUICK_OPEN(plugin);
270
271 AnjutaUI *ui;
272
273 DEBUG_PRINT("%s", "Quick Open Plugin: Deactivating plugin…");
274
275 ui = anjuta_shell_get_ui(plugin->shell, NULL);
276 anjuta_ui_remove_action_group(ui, self->action_group);
277
278 anjuta_ui_unmerge(ui, self->uiid);
279
280 anjuta_plugin_remove_watch(plugin, self->project_watch_id, FALSE);
281
282 /* Disconnect signals. */
283 if (self->project_manager)
284 {
285 g_signal_handlers_disconnect_by_func(self->project_manager, on_project_loaded, self);
286 g_object_remove_weak_pointer(G_OBJECT(self->project_manager), (void**)&self->project_manager);
287 self->project_manager = NULL;
288 }
289
290 if (self->docman)
291 {
292 g_signal_handlers_disconnect_by_func(self->docman, on_document_added, self);
293 g_signal_handlers_disconnect_by_func(self->docman, on_document_removed, self);
294 g_object_remove_weak_pointer(G_OBJECT(self->docman), (void**)&self->docman);
295 self->docman = NULL;
296 }
297
298 gtk_widget_destroy(GTK_WIDGET(self->dialog));
299
300 return TRUE;
301 }
302
303 /* GObject functions
304 *---------------------------------------------------------------------------*/
305
306 /* Used in dispose and finalize */
307 static gpointer parent_class;
308
309 static void
quick_open_plugin_instance_init(GObject * obj)310 quick_open_plugin_instance_init(GObject *obj)
311 {
312 }
313
314 static void
quick_open_plugin_finalize(GObject * obj)315 quick_open_plugin_finalize(GObject *obj)
316 {
317 G_OBJECT_CLASS(parent_class)->finalize(obj);
318 }
319
320 static void
quick_open_plugin_class_init(GObjectClass * klass)321 quick_open_plugin_class_init(GObjectClass *klass)
322 {
323 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS(klass);
324
325 parent_class = g_type_class_peek_parent(klass);
326
327 plugin_class->activate = quick_open_plugin_activate;
328 plugin_class->deactivate = quick_open_plugin_deactivate;
329 klass->finalize = quick_open_plugin_finalize;
330 }
331
332 /* AnjutaPlugin declaration
333 *---------------------------------------------------------------------------*/
334
335 ANJUTA_PLUGIN_BEGIN(QuickOpenPlugin, quick_open_plugin);
336 ANJUTA_PLUGIN_END;
337
338 ANJUTA_SIMPLE_PLUGIN(QuickOpenPlugin, quick_open_plugin);
339