1 /* gbp-todo-workspace-addin.c
2  *
3  * Copyright 2017-2019 Christian Hergert <chergert@redhat.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * SPDX-License-Identifier: GPL-3.0-or-later
19  */
20 
21 #define G_LOG_DOMAIN "gbp-todo-workspace-addin"
22 
23 #include <libide-editor.h>
24 #include <glib/gi18n.h>
25 
26 #include "gbp-todo-workspace-addin.h"
27 #include "gbp-todo-panel.h"
28 
29 struct _GbpTodoWorkspaceAddin
30 {
31   GObject       parent_instance;
32 
33   GbpTodoPanel *panel;
34   GbpTodoModel *model;
35   GCancellable *cancellable;
36   GFile        *workdir;
37 
38   guint         has_presented : 1;
39   guint         is_global_mining : 1;
40 };
41 
42 static void
gbp_todo_workspace_addin_mine_cb(GObject * object,GAsyncResult * result,gpointer user_data)43 gbp_todo_workspace_addin_mine_cb (GObject      *object,
44                                   GAsyncResult *result,
45                                   gpointer      user_data)
46 {
47   GbpTodoModel *model = (GbpTodoModel *)object;
48   g_autoptr(GbpTodoWorkspaceAddin) self = user_data;
49   g_autoptr(GError) error = NULL;
50 
51   g_assert (GBP_IS_TODO_WORKSPACE_ADDIN (self));
52   g_assert (G_IS_ASYNC_RESULT (result));
53   g_assert (GBP_IS_TODO_MODEL (model));
54 
55   /* We only do this once, safe to re-clear on per-file mining */
56   self->is_global_mining = FALSE;
57 
58   if (!gbp_todo_model_mine_finish (model, result, &error))
59     g_warning ("todo: %s", error->message);
60 
61   if (self->panel != NULL)
62     gbp_todo_panel_make_ready (self->panel);
63 }
64 
65 static void
gbp_todo_workspace_addin_presented_cb(GbpTodoWorkspaceAddin * self,GbpTodoPanel * panel)66 gbp_todo_workspace_addin_presented_cb (GbpTodoWorkspaceAddin *self,
67                                        GbpTodoPanel          *panel)
68 {
69   g_assert (GBP_IS_TODO_WORKSPACE_ADDIN (self));
70   g_assert (GBP_IS_TODO_PANEL (panel));
71 
72   if (self->has_presented)
73     return;
74 
75   self->has_presented = TRUE;
76   self->is_global_mining = TRUE;
77 
78   gbp_todo_model_mine_async (self->model,
79                              self->workdir,
80                              self->cancellable,
81                              gbp_todo_workspace_addin_mine_cb,
82                              g_object_ref (self));
83 }
84 
85 static void
gbp_todo_workspace_addin_buffer_saved(GbpTodoWorkspaceAddin * self,IdeBuffer * buffer,IdeBufferManager * bufmgr)86 gbp_todo_workspace_addin_buffer_saved (GbpTodoWorkspaceAddin *self,
87                                        IdeBuffer             *buffer,
88                                        IdeBufferManager      *bufmgr)
89 {
90   GFile *file;
91 
92   g_assert (GBP_IS_TODO_WORKSPACE_ADDIN (self));
93   g_assert (self->model != NULL);
94   g_assert (IDE_IS_BUFFER (buffer));
95   g_assert (IDE_IS_BUFFER_MANAGER (bufmgr));
96 
97   if (!self->has_presented || self->is_global_mining)
98     return;
99 
100   file = ide_buffer_get_file (buffer);
101   gbp_todo_model_mine_async (self->model,
102                              file,
103                              self->cancellable,
104                              gbp_todo_workspace_addin_mine_cb,
105                              g_object_ref (self));
106 }
107 
108 static void
gbp_todo_workspace_addin_load(IdeWorkspaceAddin * addin,IdeWorkspace * workspace)109 gbp_todo_workspace_addin_load (IdeWorkspaceAddin *addin,
110                                IdeWorkspace      *workspace)
111 {
112   GbpTodoWorkspaceAddin *self = (GbpTodoWorkspaceAddin *)addin;
113   IdeEditorSidebar *sidebar;
114   IdeBufferManager *bufmgr;
115   IdeSurface *editor;
116   IdeContext *context;
117   IdeVcs *vcs;
118   GFile *workdir;
119 
120   g_assert (GBP_IS_TODO_WORKSPACE_ADDIN (self));
121   g_assert (IDE_IS_WORKSPACE (workspace));
122 
123   self->cancellable = g_cancellable_new ();
124 
125   context = ide_workspace_get_context (workspace);
126   vcs = ide_vcs_from_context (context);
127   workdir = ide_vcs_get_workdir (vcs);
128   bufmgr = ide_buffer_manager_from_context (context);
129   editor = ide_workspace_get_surface_by_name (workspace, "editor");
130   sidebar = ide_editor_surface_get_sidebar (IDE_EDITOR_SURFACE (editor));
131 
132   self->workdir = g_object_ref (workdir);
133 
134   g_signal_connect_object (bufmgr,
135                            "buffer-saved",
136                            G_CALLBACK (gbp_todo_workspace_addin_buffer_saved),
137                            self,
138                            G_CONNECT_SWAPPED);
139 
140   self->model = gbp_todo_model_new (vcs);
141 
142   self->panel = g_object_new (GBP_TYPE_TODO_PANEL,
143                               "model", self->model,
144                               "visible", TRUE,
145                               NULL);
146   g_signal_connect_object (self->panel,
147                            "presented",
148                            G_CALLBACK (gbp_todo_workspace_addin_presented_cb),
149                            self,
150                            G_CONNECT_SWAPPED);
151   g_signal_connect (self->panel,
152                     "destroy",
153                     G_CALLBACK (gtk_widget_destroyed),
154                     &self->panel);
155   ide_editor_sidebar_add_section (sidebar,
156                                   "todo",
157                                   _("TODO/FIXMEs"),
158                                   "emblem-ok-symbolic",
159                                   NULL, NULL,
160                                   GTK_WIDGET (self->panel),
161                                   200);
162 }
163 
164 static void
gbp_todo_workspace_addin_unload(IdeWorkspaceAddin * addin,IdeWorkspace * workspace)165 gbp_todo_workspace_addin_unload (IdeWorkspaceAddin *addin,
166                                  IdeWorkspace      *workspace)
167 {
168   GbpTodoWorkspaceAddin *self = (GbpTodoWorkspaceAddin *)addin;
169   IdeBufferManager *bufmgr;
170   IdeContext *context;
171 
172   g_assert (GBP_IS_TODO_WORKSPACE_ADDIN (self));
173   g_assert (IDE_IS_WORKSPACE (workspace));
174 
175   g_cancellable_cancel (self->cancellable);
176   g_clear_object (&self->cancellable);
177 
178   context = ide_widget_get_context (GTK_WIDGET (workspace));
179   bufmgr = ide_buffer_manager_from_context (context);
180 
181   g_signal_handlers_disconnect_by_func (bufmgr,
182                                         G_CALLBACK (gbp_todo_workspace_addin_buffer_saved),
183                                         self);
184 
185   if (self->panel != NULL)
186     gtk_widget_destroy (GTK_WIDGET (self->panel));
187 
188   g_assert (self->panel == NULL);
189 
190   g_clear_object (&self->model);
191   g_clear_object (&self->workdir);
192 }
193 
194 static void
workspace_addin_iface_init(IdeWorkspaceAddinInterface * iface)195 workspace_addin_iface_init (IdeWorkspaceAddinInterface *iface)
196 {
197   iface->load = gbp_todo_workspace_addin_load;
198   iface->unload = gbp_todo_workspace_addin_unload;
199 }
200 
G_DEFINE_FINAL_TYPE_WITH_CODE(GbpTodoWorkspaceAddin,gbp_todo_workspace_addin,G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKSPACE_ADDIN,workspace_addin_iface_init))201 G_DEFINE_FINAL_TYPE_WITH_CODE (GbpTodoWorkspaceAddin, gbp_todo_workspace_addin, G_TYPE_OBJECT,
202                          G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKSPACE_ADDIN,
203                                                 workspace_addin_iface_init))
204 
205 static void
206 gbp_todo_workspace_addin_class_init (GbpTodoWorkspaceAddinClass *klass)
207 {
208 }
209 
210 static void
gbp_todo_workspace_addin_init(GbpTodoWorkspaceAddin * self)211 gbp_todo_workspace_addin_init (GbpTodoWorkspaceAddin *self)
212 {
213 }
214