1 #include <e.h>
2 #include "e_mod_main.h"
3 #include "e_mod_config.h"
4 #include "e_mod_packagekit.h"
5 
6 #define PACKAGEKIT_DOMAIN "module.packagekit"
7 
8 static E_Module *packagekit_mod = NULL;
9 
10 
11 static void
_cfg_menu_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)12 _cfg_menu_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
13 {
14    packagekit_config_show(data);
15 }
16 
17 static void
_mouse_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event)18 _mouse_down_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
19 {
20    E_PackageKit_Instance *inst = data;
21    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
22    Evas_Event_Mouse_Down *ev = event;
23 
24    if (ev->button == 1)
25      {
26         if (inst->popup)
27           packagekit_popup_del(inst);
28         else
29           packagekit_popup_new(inst, EINA_TRUE);
30      }
31    else if (ev->button == 2)
32      {
33         packagekit_create_transaction_and_exec(ctxt, packagekit_get_updates);
34      }
35    else if (ev->button == 3)
36      {
37         E_Menu *m;
38         E_Menu_Item *mi;
39         E_Zone *zone = e_zone_current_get();
40         int x, y;
41 
42         if (inst->popup)
43           packagekit_popup_del(inst);
44 
45         m = e_menu_new();
46         mi = e_menu_item_new(m);
47         e_menu_item_label_set(mi, _("Settings"));
48         e_util_menu_item_theme_icon_set(mi, "configure");
49         e_menu_item_callback_set(mi, _cfg_menu_cb, inst->ctxt);
50 
51         m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
52 
53         e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL);
54         e_menu_activate_mouse(m, zone, (x + ev->output.x),(y + ev->output.y),
55                               1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
56         evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
57                                  EVAS_BUTTON_NONE, ev->timestamp, NULL);
58      }
59 }
60 
61 static Eina_Bool
_refresh_timer_cb(void * data)62 _refresh_timer_cb(void *data)
63 {
64    E_PackageKit_Module_Context *ctxt = data;
65    double elapsed;
66 
67    if (ctxt->config->update_interval == 0)
68      return ECORE_CALLBACK_RENEW;
69 
70    elapsed = (ecore_time_unix_get() - ctxt->config->last_update) / 60;
71    if (elapsed > ctxt->config->update_interval)
72      {
73         ctxt->config->last_update = ecore_time_unix_get();
74         packagekit_create_transaction_and_exec(ctxt, packagekit_refresh_cache);
75      }
76    return ECORE_CALLBACK_RENEW;
77 }
78 
79 
80 /* Gadget Api Functions */
81 static void
_gadget_mouse_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event)82 _gadget_mouse_up_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
83 {
84    E_PackageKit_Instance *inst = data;
85    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
86    Evas_Event_Mouse_Up *ev = event;
87 
88    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
89    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
90 
91    if (ev->button == 1)
92      {
93         if (inst->ctxpopup)
94           packagekit_popup_del(inst);
95         else
96           packagekit_popup_new(inst, EINA_FALSE);
97      }
98    else if (ev->button == 2)
99      {
100         packagekit_create_transaction_and_exec(ctxt, packagekit_get_updates);
101      }
102 }
103 
104 static void
_gadget_del_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)105 _gadget_del_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
106 {
107    E_PackageKit_Instance *inst = data;
108    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
109 
110    if (inst->ctxpopup) packagekit_popup_del(inst);
111    ctxt->instances = eina_list_remove(ctxt->instances, inst);
112    free(inst);
113 }
114 
115 static Evas_Object *
_gadget_configure_cb(Evas_Object * gadget)116 _gadget_configure_cb(Evas_Object *gadget)
117 {
118    E_PackageKit_Instance *inst = evas_object_data_get(gadget, "pkit-inst");
119    return packagekit_config_show(inst->ctxt);
120 }
121 
122 static void
_gadget_menu1_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)123 _gadget_menu1_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
124 {
125    E_PackageKit_Module_Context *ctxt = data;
126 
127    e_exec(e_zone_current_get(), NULL,
128           ctxt->config->manager_command,
129           NULL, NULL);
130 }
131 
132 static void
_gadget_menu2_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)133 _gadget_menu2_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
134 {
135    E_PackageKit_Module_Context *ctxt = data;
136 
137    packagekit_create_transaction_and_exec(ctxt, packagekit_refresh_cache);
138 }
139 
140 static void
_gadget_menu_populate_cb(Evas_Object * gadget,E_Menu * m)141 _gadget_menu_populate_cb(Evas_Object *gadget, E_Menu *m)
142 {
143    E_PackageKit_Instance *inst = evas_object_data_get(gadget, "pkit-inst");
144    E_Menu_Item *mi;
145 
146    mi = e_menu_item_new(m);
147    e_menu_item_separator_set(mi, 1);
148 
149    mi = e_menu_item_new(m);
150    e_menu_item_label_set(mi, _("Refresh package list"));
151    e_util_menu_item_theme_icon_set(mi, "view-refresh");
152    e_menu_item_callback_set(mi, _gadget_menu2_cb, inst->ctxt);
153 
154    if (inst->ctxt->config->manager_command && inst->ctxt->config->manager_command[0])
155    {
156       mi = e_menu_item_new(m);
157       e_menu_item_label_set(mi, _("Run the package manager"));
158       e_util_menu_item_theme_icon_set(mi, "preferences-applications");
159       e_menu_item_callback_set(mi, _gadget_menu1_cb, inst->ctxt);
160    }
161 }
162 
163 static void
_gadget_created_cb(void * data,Evas_Object * obj,void * event_data EINA_UNUSED)164 _gadget_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
165 {
166    E_PackageKit_Instance *inst = data;
167 
168    evas_object_smart_callback_del_full(obj, "gadget_created",
169                                        _gadget_created_cb, data);
170    evas_object_event_callback_add(inst->gadget, EVAS_CALLBACK_MOUSE_UP,
171                                   _gadget_mouse_up_cb, inst);
172    e_gadget_configure_cb_set(inst->gadget, _gadget_configure_cb);
173    e_gadget_menu_populate_cb_set(inst->gadget, _gadget_menu_populate_cb);
174    packagekit_icon_update(inst->ctxt, EINA_FALSE);
175 }
176 
177 EINTERN Evas_Object *
_gadget_create_cb(Evas_Object * parent,int * id,E_Gadget_Site_Orient orient EINA_UNUSED)178 _gadget_create_cb(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
179 {
180    E_PackageKit_Instance *inst;
181    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
182 
183    inst = E_NEW(E_PackageKit_Instance, 1);
184    inst->ctxt = ctxt;
185    inst->gadget = edje_object_add(evas_object_evas_get(parent));
186    e_theme_edje_object_set(inst->gadget, "base/theme/modules/packagekit",
187                                          "e/modules/packagekit/main");
188    evas_object_event_callback_add(inst->gadget, EVAS_CALLBACK_DEL,
189                                  _gadget_del_cb, inst);
190    evas_object_data_set(inst->gadget, "pkit-inst", inst);
191    ctxt->instances = eina_list_append(ctxt->instances, inst);
192    if (*id >= 0)
193      {  // normal mode
194         evas_object_smart_callback_add(parent, "gadget_created",
195                                        _gadget_created_cb, inst);
196      }
197    else
198      {  // demo mode
199         edje_object_signal_emit(inst->gadget, "packagekit,state,updated", "e");
200      }
201 
202    return inst->gadget;
203 }
204 
205 
206 /* Gadcon Api Functions */
207 static E_Gadcon_Client *
_gc_init(E_Gadcon * gc,const char * name,const char * id,const char * style)208 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
209 {
210    E_PackageKit_Instance *inst;
211    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
212 
213    inst = E_NEW(E_PackageKit_Instance, 1);
214    inst->ctxt = ctxt;
215    inst->gadget = edje_object_add(gc->evas);
216    e_theme_edje_object_set(inst->gadget, "base/theme/modules/packagekit",
217                                          "e/modules/packagekit/main");
218    inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->gadget);
219    inst->gcc->data = inst;
220    evas_object_event_callback_add(inst->gadget, EVAS_CALLBACK_MOUSE_DOWN,
221                                   _mouse_down_cb, inst);
222    ctxt->instances = eina_list_append(ctxt->instances, inst);
223    packagekit_icon_update(ctxt, EINA_FALSE);
224    return inst->gcc;
225 }
226 
227 static void
_gc_shutdown(E_Gadcon_Client * gcc)228 _gc_shutdown(E_Gadcon_Client *gcc)
229 {
230    E_PackageKit_Instance *inst = gcc->data;
231    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
232 
233    E_FREE_FUNC(inst->gadget, evas_object_del);
234    if (inst->popup) packagekit_popup_del(inst);
235    ctxt->instances = eina_list_remove(ctxt->instances, inst);
236    free(inst);
237 }
238 
239 static void
_gc_orient(E_Gadcon_Client * gcc,E_Gadcon_Orient orient EINA_UNUSED)240 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient EINA_UNUSED)
241 {
242    e_gadcon_client_aspect_set(gcc, 16, 16);
243    e_gadcon_client_min_size_set(gcc, 16, 16);
244 }
245 
246 static const char *
_gc_label(const E_Gadcon_Client_Class * client_class EINA_UNUSED)247 _gc_label(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
248 {
249    return _("System Updates");
250 }
251 
252 static Evas_Object *
_gc_icon(const E_Gadcon_Client_Class * client_class EINA_UNUSED,Evas * evas)253 _gc_icon(const E_Gadcon_Client_Class *client_class EINA_UNUSED, Evas *evas)
254 {
255    char buf[PATH_MAX];
256    Evas_Object *o;
257 
258    EINA_SAFETY_ON_NULL_RETURN_VAL(packagekit_mod, NULL);
259    snprintf(buf, sizeof(buf), "%s/e-module-packagekit.edj",
260             e_module_dir_get(packagekit_mod));
261    o = edje_object_add(evas);
262    edje_object_file_set(o, buf, "icon");
263    return o;
264 }
265 
266 static const char *
_gc_id_new(const E_Gadcon_Client_Class * client_class EINA_UNUSED)267 _gc_id_new(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
268 {
269    E_PackageKit_Module_Context *ctxt = packagekit_mod->data;
270    static char buf[64];
271    snprintf(buf, sizeof(buf), "packagekit.%d", eina_list_count(ctxt->instances));
272    return buf;
273 }
274 
275 static const E_Gadcon_Client_Class _gc_class =
276 {
277    GADCON_CLIENT_CLASS_VERSION, "PackageKit",
278    {
279       _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
280       e_gadcon_site_is_not_toolbar
281    },
282    E_GADCON_CLIENT_STYLE_PLAIN
283 };
284 
285 
286 /* E Module Api Functions */
287 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "PackageKit" };
288 
289 E_API void *
e_modapi_init(E_Module * m)290 e_modapi_init(E_Module *m)
291 {
292    E_PackageKit_Module_Context *ctxt;
293 
294    ctxt = E_NEW(E_PackageKit_Module_Context, 1);
295    EINA_SAFETY_ON_NULL_RETURN_VAL(ctxt, NULL);
296    ctxt->v_maj = ctxt->v_min = ctxt->v_mic = -1;
297 
298    ctxt->conf_edd = E_CONFIG_DD_NEW("packagekit_config", PackageKit_Config);
299    #undef T
300    #undef D
301    #define T PackageKit_Config
302    #define D ctxt->conf_edd
303    E_CONFIG_VAL(D, T, update_interval, INT);
304    E_CONFIG_VAL(D, T, last_update, INT);
305    E_CONFIG_VAL(D, T, manager_command, STR);
306    E_CONFIG_VAL(D, T, show_description, INT);
307    ctxt->config = e_config_domain_load(PACKAGEKIT_DOMAIN, ctxt->conf_edd);
308    if (!ctxt->config)
309      {
310         ctxt->config = E_NEW(PackageKit_Config, 1);
311         ctxt->config->update_interval = 60 * 24;  // once a day
312         ctxt->config->show_description = 1;  // extended list
313      }
314    m->data = ctxt;
315    ctxt->module = m;
316    packagekit_mod = m;
317 
318    // add the gadget to the new E gadgets system
319    // TODO should this name be translated? also on type_del??
320    e_gadget_type_add("PackageKit", _gadget_create_cb, NULL);
321 
322    // add the gadget to the old E gadcon system
323    e_gadcon_provider_register(&_gc_class);
324 
325    packagekit_dbus_connect(ctxt);
326    ctxt->refresh_timer = ecore_timer_loop_add(60.0, _refresh_timer_cb, ctxt);
327    return ctxt;
328 }
329 
330 E_API int
e_modapi_shutdown(E_Module * m)331 e_modapi_shutdown(E_Module *m)
332 {
333    E_PackageKit_Module_Context *ctxt = m->data;
334 
335    packagekit_dbus_disconnect(ctxt);
336 
337    E_FREE_FUNC(ctxt->refresh_timer, ecore_timer_del);
338    E_FREE_FUNC(ctxt->error, eina_stringshare_del);
339 
340    E_FREE_FUNC(ctxt->config->manager_command, eina_stringshare_del);
341    E_FREE(ctxt->config);
342    E_CONFIG_DD_FREE(ctxt->conf_edd);
343 
344    // remove the gadget from the new E gadgets system
345    e_gadget_type_del("PackageKit");
346 
347    // remove the gadget from the old E gadcon system
348    e_gadcon_provider_unregister(&_gc_class);
349 
350    E_PackageKit_Package *pkg;
351    EINA_LIST_FREE(ctxt->packages, pkg)
352      {
353         E_FREE_FUNC(pkg->name, eina_stringshare_del);
354         E_FREE_FUNC(pkg->version, eina_stringshare_del);
355         E_FREE_FUNC(pkg->summary, eina_stringshare_del);
356      }
357 
358    E_FREE(ctxt);
359    packagekit_mod = NULL;
360 
361    return 1;
362 }
363 
364 E_API int
e_modapi_save(E_Module * m)365 e_modapi_save(E_Module *m)
366 {
367    E_PackageKit_Module_Context *ctxt = m->data;
368    e_config_domain_save(PACKAGEKIT_DOMAIN, ctxt->conf_edd, ctxt->config);
369    return 1;
370 }
371 
372 
373