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