1 #include "e.h"
2 #include "e_mod_main.h"
3 #include "e_mod_packagekit.h"
4
5
6 /* GUI */
7 void
packagekit_icon_update(E_PackageKit_Module_Context * ctxt,Eina_Bool working)8 packagekit_icon_update(E_PackageKit_Module_Context *ctxt,
9 Eina_Bool working)
10 {
11 E_PackageKit_Instance *inst;
12 E_PackageKit_Package *pkg;
13 unsigned count = 0;
14 const char *state;
15 char buf[16];
16 Eina_List *l;
17
18 if (!ctxt->instances)
19 return;
20
21 if (working)
22 state = "packagekit,state,working";
23 else if (ctxt->error)
24 state = "packagekit,state,error";
25 else
26 {
27 EINA_LIST_FOREACH(ctxt->packages, l, pkg)
28 {
29 switch (pkg->info)
30 {
31 case PK_INFO_ENUM_LOW:
32 case PK_INFO_ENUM_ENHANCEMENT:
33 case PK_INFO_ENUM_NORMAL:
34 case PK_INFO_ENUM_BUGFIX:
35 case PK_INFO_ENUM_IMPORTANT:
36 case PK_INFO_ENUM_SECURITY:
37 case PK_INFO_ENUM_AVAILABLE:
38 count++;
39 break;
40 default:
41 break;
42 }
43 }
44
45 if (count > 0)
46 state = "packagekit,state,updates";
47 else
48 state = "packagekit,state,updated";
49 }
50
51 //DBG("PKGKIT: IconUpdate, %d updates available (%s)", count, state);
52
53 if (count) snprintf(buf, sizeof(buf), "%d", count);
54 EINA_LIST_FOREACH(ctxt->instances, l, inst)
55 {
56 edje_object_signal_emit(inst->gadget, state, "e");
57 edje_object_part_text_set(inst->gadget, "num_updates", count ? buf : "");
58 }
59 }
60
61 static void
_update_button_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)62 _update_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
63 void *event EINA_UNUSED)
64 {
65 E_PackageKit_Instance *inst = data;
66
67 packagekit_create_transaction_and_exec(inst->ctxt, packagekit_refresh_cache);
68 }
69
70 static char *
_help_gl_text_get(void * data,Evas_Object * obj EINA_UNUSED,const char * part)71 _help_gl_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
72 {
73 PackageKit_Package_Info info = (PackageKit_Package_Info)data;
74
75 if (strcmp(part, "elm.text"))
76 return NULL;
77
78 switch (info)
79 {
80 case PK_INFO_ENUM_LOW:
81 return strdup(_("Low priority update"));
82 case PK_INFO_ENUM_ENHANCEMENT:
83 return strdup(_("Enhancement update"));
84 case PK_INFO_ENUM_NORMAL:
85 return strdup(_("Normal update"));
86 case PK_INFO_ENUM_BUGFIX:
87 return strdup(_("Bugfix update"));
88 case PK_INFO_ENUM_IMPORTANT:
89 return strdup(_("High priority update"));
90 case PK_INFO_ENUM_SECURITY:
91 return strdup(_("Security update"));
92 default:
93 return NULL;
94 }
95 }
96
97 static Evas_Object *
_help_gl_content_get(void * data,Evas_Object * obj,const char * part)98 _help_gl_content_get(void *data, Evas_Object *obj, const char *part)
99 {
100 PackageKit_Package_Info info = (PackageKit_Package_Info)data;
101 const char *emblem_name;
102 Evas_Object *icon;
103
104 if (strcmp(part, "elm.swallow.icon"))
105 return NULL;
106
107 switch (info)
108 {
109 case PK_INFO_ENUM_LOW:
110 emblem_name = "e/modules/packagekit/icon/low"; break;
111 case PK_INFO_ENUM_ENHANCEMENT:
112 emblem_name = "e/modules/packagekit/icon/enhancement"; break;
113 case PK_INFO_ENUM_NORMAL:
114 emblem_name = "e/modules/packagekit/icon/normal"; break;
115 case PK_INFO_ENUM_BUGFIX:
116 emblem_name = "e/modules/packagekit/icon/bugfix"; break;
117 case PK_INFO_ENUM_IMPORTANT:
118 emblem_name = "e/modules/packagekit/icon/important"; break;
119 case PK_INFO_ENUM_SECURITY:
120 emblem_name = "e/modules/packagekit/icon/security"; break;
121 default:
122 return NULL; break;
123 }
124
125 icon = edje_object_add(evas_object_evas_get(obj));
126 e_theme_edje_object_set(icon, "base/theme/modules/packagekit", emblem_name);
127
128 return icon;
129 }
130
131 static void
_help_button_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)132 _help_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
133 void *event EINA_UNUSED)
134 {
135 E_PackageKit_Instance *inst = data;
136 Elm_Genlist_Item_Class *help_itc;
137 char buf[1024];
138 long i;
139
140 if (inst->popup_help_mode)
141 {
142 inst->popup_help_mode = EINA_FALSE;
143 packagekit_popup_update(inst, EINA_TRUE);
144 return;
145 }
146 inst->popup_help_mode = EINA_TRUE;
147
148 // special item class for help items
149 help_itc = elm_genlist_item_class_new();
150 help_itc->item_style = "default";
151 help_itc->func.text_get = _help_gl_text_get;
152 help_itc->func.content_get = _help_gl_content_get;
153
154 // repopulate the genlist
155 elm_genlist_clear(inst->popup_genlist);
156 for (i = PK_INFO_ENUM_LOW; i <= PK_INFO_ENUM_SECURITY; i++)
157 {
158 Elm_Genlist_Item *it;
159 it = elm_genlist_item_append(inst->popup_genlist, help_itc, (void*)i,
160 NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
161 elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
162 }
163
164 elm_genlist_item_class_free(help_itc);
165
166 // update title label
167 if (inst->ctxt->v_maj != -1)
168 snprintf(buf, sizeof(buf), "PackageKit version: %d.%d.%d",
169 inst->ctxt->v_maj, inst->ctxt->v_min, inst->ctxt->v_mic);
170 else
171 snprintf(buf, sizeof(buf), _("Unknown PackageKit version"));
172 elm_object_text_set(inst->popup_title_entry, buf);
173 }
174
175 static void
_install_button_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)176 _install_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
177 void *event EINA_UNUSED)
178 {
179 E_PackageKit_Instance *inst = data;
180 E_PackageKit_Package *pkg;
181 const Eina_List *selected;
182 Elm_Genlist_Item *item;
183 Eina_List *l;
184
185 selected = elm_genlist_selected_items_get(inst->popup_genlist);
186 if (!selected)
187 {
188 // nothing selected, update all packages
189 EINA_LIST_FOREACH(inst->ctxt->packages, l, pkg)
190 pkg->to_be_installed = EINA_TRUE;
191 }
192 else
193 {
194 // only updated selected packages
195 EINA_LIST_FOREACH(inst->ctxt->packages, l, pkg)
196 pkg->to_be_installed = EINA_FALSE;
197 EINA_LIST_FOREACH((Eina_List*)selected, l, item)
198 {
199 pkg = elm_object_item_data_get(item);
200 pkg->to_be_installed = EINA_TRUE;
201 }
202 }
203
204 packagekit_create_transaction_and_exec(inst->ctxt, packagekit_update_packages);
205 }
206
207 static void
_run_button_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)208 _run_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
209 void *event EINA_UNUSED)
210 {
211 E_PackageKit_Instance *inst = data;
212 packagekit_popup_del(inst);
213
214 e_exec(e_zone_current_get(), NULL,
215 inst->ctxt->config->manager_command,
216 NULL, NULL);
217 }
218
219 void
packagekit_popup_update(E_PackageKit_Instance * inst,Eina_Bool rebuild_list)220 packagekit_popup_update(E_PackageKit_Instance *inst, Eina_Bool rebuild_list)
221 {
222 E_PackageKit_Module_Context *ctxt = inst->ctxt;
223 E_PackageKit_Package *pkg;
224 const Eina_List *selected;
225 unsigned num_updates = 0;
226 char buf[1024];
227 Eina_List *l;
228
229 if (!inst->popup_genlist) return;
230
231 if (inst->popup_help_mode)
232 inst->popup_help_mode = EINA_FALSE;
233
234 if (rebuild_list)
235 elm_genlist_clear(inst->popup_genlist);
236
237 if (ctxt->error)
238 {
239 elm_object_text_set(inst->popup_title_entry, _("No information available"));
240 elm_object_text_set(inst->popup_error_label, ctxt->error);
241 if ((ctxt->v_maj != -1) && (ctxt->v_min != -1) && (ctxt->v_mic != -1))
242 {
243 snprintf(buf, sizeof(buf), "<ps/>PackageKit version: %d.%d.%d",
244 ctxt->v_maj, ctxt->v_min, ctxt->v_mic);
245 elm_entry_entry_append(inst->popup_error_label, buf);
246 }
247 return;
248 }
249
250 EINA_LIST_FOREACH(ctxt->packages, l, pkg)
251 {
252 if (rebuild_list)
253 elm_genlist_item_append(inst->popup_genlist, inst->popup_genlist_itc,
254 pkg, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
255 num_updates++;
256 }
257
258 // show the progress bar if an operation is in progress
259 if (ctxt->transaction)
260 {
261 elm_genlist_clear(inst->popup_genlist);
262 elm_progressbar_value_set(inst->popup_progressbar,
263 ctxt->transaction_progress);
264 evas_object_show(inst->popup_progressbar_frame);
265 }
266 else
267 evas_object_hide(inst->popup_progressbar_frame);
268
269 // update title and error lables
270 if (ctxt->transaction)
271 snprintf(buf, sizeof(buf), _("Operation in progress"));
272 else if (num_updates >= 1)
273 snprintf(buf, sizeof(buf), P_("One update available", "%d updates available", num_updates), num_updates);
274 else
275 snprintf(buf, sizeof(buf), _("Your system is updated"));
276 elm_object_text_set(inst->popup_title_entry, buf);
277 elm_object_text_set(inst->popup_error_label, "");
278
279 // update the status of the install button
280 selected = elm_genlist_selected_items_get(inst->popup_genlist);
281 if (ctxt->transaction)
282 {
283 elm_object_text_set(inst->popup_install_button, _("Please wait"));
284 elm_object_disabled_set(inst->popup_install_button, EINA_TRUE);
285 }
286 else if (num_updates < 1)
287 {
288 elm_object_text_set(inst->popup_install_button, _("Nothing to do"));
289 elm_object_disabled_set(inst->popup_install_button, EINA_TRUE);
290 }
291 else if ((selected == NULL) || (eina_list_count(selected) == 0))
292 {
293 elm_object_text_set(inst->popup_install_button,
294 _("Install all available updates"));
295 elm_object_disabled_set(inst->popup_install_button, EINA_FALSE);
296 }
297 else if (eina_list_count(selected) > 0)
298 {
299 snprintf(buf, sizeof(buf), P_("Install the selected update",
300 "Install %d selected updates",
301 eina_list_count(selected)),
302 eina_list_count(selected));
303 elm_object_text_set(inst->popup_install_button, buf);
304 elm_object_disabled_set(inst->popup_install_button, EINA_FALSE);
305 }
306 }
307
308 void
packagekit_all_popups_update(E_PackageKit_Module_Context * ctxt,Eina_Bool rebuild_list)309 packagekit_all_popups_update(E_PackageKit_Module_Context *ctxt,
310 Eina_Bool rebuild_list)
311 {
312 E_PackageKit_Instance *inst;
313 Eina_List *l;
314
315 EINA_LIST_FOREACH(ctxt->instances, l, inst)
316 packagekit_popup_update(inst, rebuild_list);
317 }
318
319 void
packagekit_progress_percentage_update(E_PackageKit_Module_Context * ctxt,int percent)320 packagekit_progress_percentage_update(E_PackageKit_Module_Context *ctxt,
321 int percent)
322 {
323 E_PackageKit_Instance *inst;
324 Eina_List *l;
325 double val = (double)percent / 100.0;
326
327 ctxt->transaction_progress = val;
328 EINA_LIST_FOREACH(ctxt->instances, l, inst)
329 if (inst->popup_progressbar)
330 elm_progressbar_value_set(inst->popup_progressbar, val);
331 }
332
333 static void
_popup_del_cb(void * obj)334 _popup_del_cb(void *obj)
335 {
336 packagekit_popup_del(e_object_data_get(obj));
337 }
338
339 static char *
_gl_item_single_text_get(void * data,Evas_Object * obj EINA_UNUSED,const char * part)340 _gl_item_single_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
341 {
342 E_PackageKit_Package *pkg = data;
343
344 if (!strcmp(part, "elm.text"))
345 {
346 char *s = malloc(strlen(pkg->name) + strlen(pkg->version) + 2);
347 sprintf(s, "%s %s", pkg->name, pkg->version);
348 return s;
349 }
350
351 return NULL;
352 }
353
354 static char *
_gl_item_double_text_get(void * data,Evas_Object * obj EINA_UNUSED,const char * part)355 _gl_item_double_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
356 {
357 E_PackageKit_Package *pkg = data;
358
359 if (!strcmp(part, "elm.text"))
360 {
361 return strdup(pkg->summary);
362 }
363 else
364 {
365 char *s = malloc(strlen(pkg->name) + strlen(pkg->version) + 2);
366 sprintf(s, "%s %s", pkg->name, pkg->version);
367 return s;
368 }
369
370 return NULL;
371 }
372
373 static Evas_Object *
_gl_item_content_get(void * data,Evas_Object * obj,const char * part)374 _gl_item_content_get(void *data, Evas_Object *obj, const char *part)
375 {
376 E_PackageKit_Package *pkg = data;
377 Efreet_Desktop *desktop;
378 Evas_Object *icon;
379
380 if (!strcmp(part, "elm.swallow.icon"))
381 {
382 // get the priority icon from the theme
383 const char *emblem_name;
384
385 switch (pkg->info)
386 {
387 case PK_INFO_ENUM_LOW:
388 emblem_name = "e/modules/packagekit/icon/low"; break;
389 case PK_INFO_ENUM_ENHANCEMENT:
390 emblem_name = "e/modules/packagekit/icon/enhancement"; break;
391 case PK_INFO_ENUM_NORMAL:
392 emblem_name = "e/modules/packagekit/icon/normal"; break;
393 case PK_INFO_ENUM_BUGFIX:
394 emblem_name = "e/modules/packagekit/icon/bugfix"; break;
395 case PK_INFO_ENUM_IMPORTANT:
396 emblem_name = "e/modules/packagekit/icon/important"; break;
397 case PK_INFO_ENUM_SECURITY:
398 emblem_name = "e/modules/packagekit/icon/security"; break;
399 default:
400 emblem_name = NULL; break;
401 }
402 if (emblem_name)
403 {
404 icon = edje_object_add(evas_object_evas_get(obj));
405 e_theme_edje_object_set(icon, "base/theme/modules/packagekit", emblem_name);
406 return icon;
407 }
408 }
409 else if (!strcmp(part, "elm.swallow.end"))
410 {
411 // try to find a desktop file that match the executable or the name
412 desktop = efreet_util_desktop_exec_find(pkg->name);
413 if (!desktop)
414 desktop = efreet_util_desktop_name_find(pkg->name);
415
416 if (desktop && desktop->icon)
417 {
418 icon = elm_icon_add(obj);
419 elm_icon_standard_set(icon, desktop->icon);
420 efreet_desktop_free(desktop);
421 return icon;
422 }
423 }
424
425 return NULL;
426 }
427
428 static void
_genlist_selunsel_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)429 _genlist_selunsel_cb(void *data, Evas_Object *obj EINA_UNUSED,
430 void *event EINA_UNUSED)
431 {
432 packagekit_popup_update(data, EINA_FALSE);
433 }
434
435 static void
_ctxpopup_dismissed(void * data,Evas_Object * obj,void * info EINA_UNUSED)436 _ctxpopup_dismissed(void *data, Evas_Object *obj, void *info EINA_UNUSED)
437 {
438 E_PackageKit_Instance *inst = data;
439
440 evas_object_del(obj);
441 inst->ctxpopup = NULL;
442 }
443
444 void
packagekit_popup_new(E_PackageKit_Instance * inst,Eina_Bool is_gadcon)445 packagekit_popup_new(E_PackageKit_Instance *inst, Eina_Bool is_gadcon)
446 {
447 Evas_Object *table, *bt, *ic, *lb, *li, *pb, *fr, *bx, *size_rect;
448 const char *p;
449
450 if (is_gadcon)
451 {
452 inst->popup = e_gadcon_popup_new(inst->gcc, EINA_FALSE);
453 table = elm_table_add(e_comp->elm);
454 }
455 else
456 {
457 inst->ctxpopup = elm_ctxpopup_add(e_comp->elm);
458 elm_object_style_set(inst->ctxpopup, "noblock");
459 evas_object_smart_callback_add(inst->ctxpopup, "dismissed",
460 _ctxpopup_dismissed, inst);
461 table = elm_table_add(inst->ctxpopup);
462 }
463 evas_object_show(table);
464
465 // horiz box for title and buttons
466 bx = elm_box_add(table);
467 elm_box_horizontal_set(bx, EINA_TRUE);
468 evas_object_size_hint_expand_set(bx, EVAS_HINT_EXPAND, 0.0);
469 evas_object_size_hint_fill_set(bx, EVAS_HINT_FILL, 0.0);
470 elm_table_pack(table, bx, 0, 0, 1, 1);
471 evas_object_show(bx);
472
473 // title label
474 lb = inst->popup_title_entry = elm_entry_add(table);
475 elm_entry_editable_set(lb, 0);
476 evas_object_size_hint_expand_set(lb, EVAS_HINT_EXPAND, 0.0);
477 evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, 0.5);
478 elm_entry_text_style_user_push(lb, "DEFAULT='font_weight=Bold'");
479 elm_box_pack_end(bx, lb);
480 evas_object_show(lb);
481
482 // refresh button
483 ic = elm_icon_add(table);
484 evas_object_size_hint_min_set(ic, 16 * elm_config_scale_get(),
485 16 * elm_config_scale_get());
486 elm_icon_standard_set(ic, "view-refresh");
487 bt = elm_button_add(table);
488 elm_object_content_set(bt, ic);
489 evas_object_smart_callback_add(bt, "clicked", _update_button_cb, inst);
490 elm_box_pack_end(bx, bt);
491 evas_object_show(bt);
492
493 // help button
494 ic = elm_icon_add(table);
495 evas_object_size_hint_min_set(ic, 16 * elm_config_scale_get(),
496 16 * elm_config_scale_get());
497 elm_icon_standard_set(ic, "help-contents");
498 bt = elm_button_add(table);
499 elm_object_content_set(bt, ic);
500 evas_object_smart_callback_add(bt, "clicked", _help_button_cb, inst);
501 elm_box_pack_end(bx, bt);
502 evas_object_show(bt);
503
504 // central area (sizer)
505 size_rect = evas_object_rectangle_add(evas_object_evas_get(table));
506 evas_object_size_hint_min_set(size_rect, 300 * elm_config_scale_get(),
507 300 * elm_config_scale_get());
508 elm_table_pack(table, size_rect, 0, 1, 1, 1);
509
510 // central area (error label)
511 lb = inst->popup_error_label = elm_entry_add(table);
512 elm_entry_editable_set(lb, EINA_FALSE);
513 E_EXPAND(lb);
514 E_FILL(lb);
515 elm_table_pack(table, lb, 0, 1, 1, 1);
516 evas_object_show(lb);
517
518 // central area (genlist)
519 inst->popup_genlist_itc = elm_genlist_item_class_new();
520 if (inst->ctxt->config->show_description)
521 {
522 inst->popup_genlist_itc->item_style = "double_label";
523 inst->popup_genlist_itc->func.text_get = _gl_item_double_text_get;
524 }
525 else
526 {
527 inst->popup_genlist_itc->item_style = "default";
528 inst->popup_genlist_itc->func.text_get = _gl_item_single_text_get;
529 }
530 inst->popup_genlist_itc->func.content_get = _gl_item_content_get;
531
532 li = inst->popup_genlist = elm_genlist_add(table);
533 elm_genlist_homogeneous_set(li, EINA_TRUE);
534 elm_genlist_mode_set(li, ELM_LIST_COMPRESS);
535 elm_genlist_multi_select_set(li, EINA_TRUE);
536 E_EXPAND(li);
537 E_FILL(li);
538 evas_object_smart_callback_add(li, "selected", _genlist_selunsel_cb, inst);
539 evas_object_smart_callback_add(li, "unselected", _genlist_selunsel_cb, inst);
540 elm_table_pack(table, li, 0, 1, 1, 1);
541 evas_object_show(li);
542
543 // central area (progress bar) (inside a padding frame)
544 fr = inst->popup_progressbar_frame = elm_frame_add(table);
545 elm_object_style_set(fr, "pad_large");
546 E_EXPAND(fr);
547 E_FILL(fr);
548 elm_table_pack(table, fr, 0, 1, 1, 1);
549 evas_object_show(fr);
550
551 pb = inst->popup_progressbar = elm_progressbar_add(table);
552 E_EXPAND(pb);
553 E_FILL(pb);
554 elm_object_content_set(fr, pb);
555
556 // install button
557 bt = inst->popup_install_button = elm_button_add(table);
558 evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, 0.0);
559 evas_object_smart_callback_add(bt, "clicked", _install_button_cb, inst);
560 elm_table_pack(table, bt, 0, 2, 1, 1);
561 evas_object_show(bt);
562
563 // run package manager button (only if configured)
564 p = inst->ctxt->config->manager_command;
565 if (p && p[0])
566 {
567 bt = elm_button_add(table);
568 evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, 0.0);
569 elm_object_text_set(bt, _("Run the package manager"));
570 evas_object_smart_callback_add(bt, "clicked", _run_button_cb, inst);
571 elm_table_pack(table, bt, 0, 3, 1, 1);
572 evas_object_show(bt);
573 }
574
575 // setup and show the popup
576 if (is_gadcon)
577 {
578 e_gadcon_popup_content_set(inst->popup, table);
579 e_object_data_set(E_OBJECT(inst->popup), inst);
580 E_OBJECT_DEL_SET(inst->popup, _popup_del_cb);
581 e_gadcon_popup_show(inst->popup);
582 }
583 else
584 {
585 elm_object_content_set(inst->ctxpopup, table);
586 e_gadget_util_ctxpopup_place(inst->gadget, inst->ctxpopup, NULL);
587 evas_object_show(inst->ctxpopup);
588 }
589
590 // update the popup state and contents
591 packagekit_popup_update(inst, EINA_TRUE);
592 }
593
594 void
packagekit_popup_del(E_PackageKit_Instance * inst)595 packagekit_popup_del(E_PackageKit_Instance *inst)
596 {
597 if (inst->popup)
598 E_FREE_FUNC(inst->popup, e_object_del);
599 if (inst->ctxpopup)
600 elm_ctxpopup_dismiss(inst->ctxpopup);
601
602 inst->popup_genlist = inst->popup_title_entry = NULL;
603 inst->popup_progressbar = inst->popup_progressbar_frame = NULL;
604 if (inst->popup_genlist_itc)
605 {
606 elm_genlist_item_class_free(inst->popup_genlist_itc);
607 inst->popup_genlist_itc = NULL;
608 }
609 }
610
611 static void
_store_error(E_PackageKit_Module_Context * ctxt,const char * err)612 _store_error(E_PackageKit_Module_Context *ctxt, const char *err)
613 {
614 ERR("PKGKIT: ERROR: %s", err);
615 if (ctxt->error)
616 eina_stringshare_replace(&ctxt->error, err);
617 else
618 ctxt->error = eina_stringshare_add(err);
619 packagekit_icon_update(ctxt, EINA_FALSE);
620 packagekit_all_popups_update(ctxt, EINA_FALSE);
621 }
622
623 /* DBus PackageKit method calls */
624
625 static void
null_cb(void * data,const Eldbus_Message * msg,Eldbus_Pending * pending EINA_UNUSED)626 null_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
627 {
628 E_PackageKit_Module_Context *ctxt = data;
629 const char *error, *error_msg;
630
631 if (eldbus_message_error_get(msg, &error, &error_msg))
632 _store_error(ctxt, error_msg);
633 }
634
635
636 /* RefreshCache(in'b'force) */
637 static void
_signal_repo_detail_cb(void * data,const Eldbus_Message * msg)638 _signal_repo_detail_cb(void *data, const Eldbus_Message *msg)
639 { /* RepoDetail ('s'repo_id, 's'description, 'b'enabled) */
640 E_PackageKit_Module_Context *ctxt = data;
641 const char *error, *error_msg, *repo_id, *desc;
642 Eina_Bool enabled;
643
644 if (eldbus_message_error_get(msg, &error, &error_msg))
645 {
646 _store_error(ctxt, error_msg);
647 return;
648 }
649 if (!eldbus_message_arguments_get(msg, "ssb", &repo_id, &desc, &enabled))
650 {
651 _store_error(ctxt, "could not get arguments (ssb)");
652 return;
653 }
654 //DBG("PKGKIT: RepoDetail: (%d) %s [ %s ]", enabled, repo_id, desc);
655 }
656
657 static void
_signal_cache_finished_cb(void * data,const Eldbus_Message * msg)658 _signal_cache_finished_cb(void *data, const Eldbus_Message *msg)
659 { /* Finished ('u'exit, 'u'runtime) */
660 E_PackageKit_Module_Context *ctxt = data;
661 const char *error, *error_msg;
662
663 //DBG("PKGKIT: Cache Finished CB");
664
665 if (eldbus_message_error_get(msg, &error, &error_msg))
666 {
667 _store_error(ctxt, error_msg);
668 return;
669 }
670
671 Eldbus_Object *obj = eldbus_proxy_object_get(ctxt->transaction);
672 E_FREE_FUNC(ctxt->transaction, eldbus_proxy_unref);
673 E_FREE_FUNC(obj, eldbus_object_unref);
674
675 packagekit_create_transaction_and_exec(ctxt, packagekit_get_updates);
676 }
677
678 void
packagekit_refresh_cache(E_PackageKit_Module_Context * ctxt,const char * transaction)679 packagekit_refresh_cache(E_PackageKit_Module_Context *ctxt, const char *transaction)
680 {
681 Eldbus_Object *obj;
682 Eldbus_Proxy *proxy;
683 Eldbus_Pending *pending;
684
685 ctxt->config->last_update = ecore_time_unix_get();
686
687 obj = eldbus_object_get(ctxt->conn, "org.freedesktop.PackageKit", transaction);
688 proxy = eldbus_proxy_get(obj, "org.freedesktop.PackageKit.Transaction");
689 pending = eldbus_proxy_call(proxy, "RefreshCache", null_cb, ctxt, -1, "b", 1);
690 if (!pending)
691 {
692 _store_error(ctxt, "could not call RefreshCache()");
693 return;
694 }
695 eldbus_proxy_signal_handler_add(proxy, "Finished",
696 _signal_cache_finished_cb, ctxt);
697 eldbus_proxy_signal_handler_add(proxy, "RepoDetail",
698 _signal_repo_detail_cb, ctxt);
699 ctxt->transaction = proxy;
700 }
701
702
703 /* GetUpdates(in't'filter) */
704 static void
_signal_package_cb(void * data,const Eldbus_Message * msg)705 _signal_package_cb(void *data, const Eldbus_Message *msg)
706 { /* Package ('u'info, 's'package_id, 's'summary) */
707 const char *error, *error_msg, *pkg_id, *summary, *info_str;
708 E_PackageKit_Module_Context *ctxt = data;
709 PackageKit_Package_Info info;
710 unsigned num_elements = 0;
711 char **splitted;
712 Eina_Bool ret;
713
714 if (eldbus_message_error_get(msg, &error, &error_msg))
715 {
716 _store_error(ctxt, error_msg);
717 return;
718 }
719 if (PKITV07)
720 ret = eldbus_message_arguments_get(msg, "sss", &info_str, &pkg_id, &summary);
721 else
722 ret = eldbus_message_arguments_get(msg, "uss", &info, &pkg_id, &summary);
723 if (!ret)
724 {
725 _store_error(ctxt, "could not get package arguments");
726 return;
727 }
728 //if (PKITV07)
729 //{ DBG("PKGKIT: Package: (%s) %s [ %s ]", info_str, pkg_id, summary); }
730 //else
731 //{ DBG("PKGKIT: Package: (%d) %s [ %s ]", info, pkg_id, summary); }
732
733 splitted = eina_str_split_full(pkg_id, ";", 3, &num_elements);
734 if (num_elements >= 2)
735 {
736 E_PackageKit_Package *pkg = E_NEW(E_PackageKit_Package, 1);
737 pkg->pkg_id = eina_stringshare_add(pkg_id);
738 pkg->name = eina_stringshare_add(splitted[0]);
739 pkg->version = eina_stringshare_add(splitted[1]);
740 pkg->summary = eina_stringshare_add(summary);
741 if (PKITV07)
742 {
743 if (!info_str) pkg->info = PK_INFO_ENUM_NORMAL;
744 else if (!strcmp(info_str, "normal")) pkg->info = PK_INFO_ENUM_NORMAL;
745 else if (!strcmp(info_str, "security")) pkg->info = PK_INFO_ENUM_SECURITY;
746 else if (!strcmp(info_str, "blocked")) pkg->info = PK_INFO_ENUM_BLOCKED;
747 else if (!strcmp(info_str, "low")) pkg->info = PK_INFO_ENUM_LOW;
748 else if (!strcmp(info_str, "enhancement")) pkg->info = PK_INFO_ENUM_ENHANCEMENT;
749 else if (!strcmp(info_str, "bugfix")) pkg->info = PK_INFO_ENUM_BUGFIX;
750 else if (!strcmp(info_str, "important")) pkg->info = PK_INFO_ENUM_IMPORTANT;
751 else pkg->info = PK_INFO_ENUM_UNKNOWN;
752 }
753 else
754 pkg->info = info;
755 ctxt->packages = eina_list_append(ctxt->packages, pkg);
756 }
757 if (splitted)
758 {
759 free(splitted[0]);
760 free(splitted);
761 }
762 }
763
764 static void
_signal_finished_cb(void * data,const Eldbus_Message * msg)765 _signal_finished_cb(void *data, const Eldbus_Message *msg)
766 { /* Finished ('u'exit, 'u'runtime) */
767 const char *error, *error_msg;
768 E_PackageKit_Module_Context *ctxt = data;
769
770 if (eldbus_message_error_get(msg, &error, &error_msg))
771 {
772 _store_error(ctxt, error_msg);
773 return;
774 }
775
776 Eldbus_Object *obj = eldbus_proxy_object_get(ctxt->transaction);
777 E_FREE_FUNC(ctxt->transaction, eldbus_proxy_unref);
778 E_FREE_FUNC(obj, eldbus_object_unref);
779 E_FREE_FUNC(ctxt->error, eina_stringshare_del);
780
781 //DBG("PKGKIT: PackageFinished");
782 packagekit_icon_update(ctxt, EINA_FALSE);
783 packagekit_all_popups_update(ctxt, EINA_TRUE);
784 }
785
786 void
packagekit_get_updates(E_PackageKit_Module_Context * ctxt,const char * transaction)787 packagekit_get_updates(E_PackageKit_Module_Context *ctxt, const char *transaction)
788 {
789 Eldbus_Object *obj;
790 Eldbus_Proxy *proxy;
791 Eldbus_Pending *pending;
792 E_PackageKit_Package *pkg;
793
794 obj = eldbus_object_get(ctxt->conn, "org.freedesktop.PackageKit", transaction);
795 proxy = eldbus_proxy_get(obj, "org.freedesktop.PackageKit.Transaction");
796 if (PKITV07)
797 pending = eldbus_proxy_call(proxy, "GetUpdates", null_cb, ctxt, -1, "s", "none");
798 else
799 pending = eldbus_proxy_call(proxy, "GetUpdates", null_cb, ctxt, -1, "t", 1);
800 if (!pending)
801 {
802 _store_error(ctxt, "could not call GetUpdates()");
803 return;
804 }
805
806 eldbus_proxy_signal_handler_add(proxy, "Package", _signal_package_cb, ctxt);
807 eldbus_proxy_signal_handler_add(proxy, "Finished", _signal_finished_cb, ctxt);
808 ctxt->transaction = proxy;
809
810 EINA_LIST_FREE(ctxt->packages, pkg)
811 {
812 E_FREE_FUNC(pkg->pkg_id, eina_stringshare_del);
813 E_FREE_FUNC(pkg->name, eina_stringshare_del);
814 E_FREE_FUNC(pkg->version, eina_stringshare_del);
815 E_FREE_FUNC(pkg->summary, eina_stringshare_del);
816 }
817 }
818
819
820 /* UpdatePackages(in't'transaction_flags, in'as'package_ids) */
821 static void
_signal_update_error_code_cb(void * data,const Eldbus_Message * msg)822 _signal_update_error_code_cb(void *data, const Eldbus_Message *msg)
823 { /* ErrorCode ('u'code, 's'details) */
824 const char *error, *error_msg, *details;
825 E_PackageKit_Module_Context *ctxt = data;
826 Eina_Bool ret;
827 int err_code;
828
829 if (eldbus_message_error_get(msg, &error, &error_msg))
830 {
831 _store_error(ctxt, error_msg);
832 return;
833 }
834
835 ret = eldbus_message_arguments_get(msg, "us", &err_code, &details);
836 if (!ret)
837 {
838 _store_error(ctxt, "could not get error code arguments");
839 return;
840 }
841
842 if (details)
843 _store_error(ctxt, details);
844 }
845
846 static void
_signal_update_finished_cb(void * data,const Eldbus_Message * msg)847 _signal_update_finished_cb(void *data, const Eldbus_Message *msg)
848 { /* Finished ('u'exit, 'u'runtime) */
849 const char *error, *error_msg;
850 E_PackageKit_Module_Context *ctxt = data;
851
852 if (eldbus_message_error_get(msg, &error, &error_msg))
853 _store_error(ctxt, error_msg);
854 else
855 E_FREE_FUNC(ctxt->error, eina_stringshare_del);
856
857 Eldbus_Object *obj = eldbus_proxy_object_get(ctxt->transaction);
858 E_FREE_FUNC(ctxt->transaction, eldbus_proxy_unref);
859 E_FREE_FUNC(obj, eldbus_object_unref);
860 }
861
862 void
packagekit_update_packages(E_PackageKit_Module_Context * ctxt,const char * transaction)863 packagekit_update_packages(E_PackageKit_Module_Context *ctxt, const char *transaction)
864 {
865 Eldbus_Object *obj;
866 Eldbus_Proxy *proxy;
867 Eldbus_Message *msg;
868 Eldbus_Message_Iter *iter, *array_of_string;
869 Eldbus_Pending *pending;
870 E_PackageKit_Package *pkg;
871 Eina_List *l;
872
873 fprintf(stderr, "PKIT: UpdatePackages (t:%s)\n", transaction);
874
875 obj = eldbus_object_get(ctxt->conn, "org.freedesktop.PackageKit", transaction);
876 proxy = eldbus_proxy_get(obj, "org.freedesktop.PackageKit.Transaction");
877 msg = eldbus_proxy_method_call_new(proxy, "UpdatePackages");
878 iter = eldbus_message_iter_get(msg);
879 eldbus_message_iter_arguments_append(iter, "tas",
880 PK_TRANSACTION_FLAG_ENUM_ONLY_TRUSTED,
881 &array_of_string);
882 EINA_LIST_FOREACH(ctxt->packages, l, pkg)
883 {
884 if (pkg->to_be_installed)
885 {
886 DBG("Install: %s %s", pkg->pkg_id, pkg->version);
887 eldbus_message_iter_arguments_append(array_of_string, "s", pkg->pkg_id);
888 }
889 }
890 eldbus_message_iter_container_close(iter, array_of_string);
891
892 pending = eldbus_proxy_send(proxy, msg, null_cb, ctxt, -1);
893 if (!pending)
894 {
895 _store_error(ctxt, "could not call UpdatePackages()");
896 return;
897 }
898 eldbus_proxy_signal_handler_add(proxy, "ErrorCode",
899 _signal_update_error_code_cb, ctxt);
900 eldbus_proxy_signal_handler_add(proxy, "Finished",
901 _signal_update_finished_cb, ctxt);
902 ctxt->transaction = proxy;
903 }
904
905 /* CreateTransaction() */
906 static void
_transaction_changed_props_iter(void * data,const void * key,Eldbus_Message_Iter * val)907 _transaction_changed_props_iter(void *data, const void *key,
908 Eldbus_Message_Iter *val)
909 {
910 E_PackageKit_Module_Context *ctxt = data;
911
912 if (!strcmp(key, "Percentage"))
913 {
914 int val_int;
915 eldbus_message_iter_basic_get(val, &val_int);
916 packagekit_progress_percentage_update(ctxt, val_int);
917 }
918 }
919
920 static void
_signal_transaction_props_changed_cb(void * data,const Eldbus_Message * msg)921 _signal_transaction_props_changed_cb(void *data, const Eldbus_Message *msg)
922 { /* PropertiesChanged('s'interface_name, 'a{sv}'changed_properties,
923 'as' invalidated_properties) */
924 E_PackageKit_Module_Context *ctxt = data;
925 const char *error, *error_msg, *interface_name;
926 Eldbus_Message_Iter *changed_properties, *invalidated_properties;
927 Eina_Bool ret;
928
929 if (eldbus_message_error_get(msg, &error, &error_msg))
930 {
931 _store_error(ctxt, error_msg);
932 return;
933 }
934
935 ret = eldbus_message_arguments_get(msg, "sa{sv}as", &interface_name,
936 &changed_properties,
937 &invalidated_properties);
938 if (!ret)
939 {
940 _store_error(ctxt, "could not get signal arguments");
941 return;
942 }
943
944 eldbus_message_iter_dict_iterate(changed_properties, "sv",
945 _transaction_changed_props_iter, ctxt);
946 }
947
948 static void
_transaction_created_cb(void * data,const Eldbus_Message * msg,Eldbus_Pending * pending)949 _transaction_created_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
950 {
951 const char *error, *error_msg, *trans_path;
952 E_PackageKit_Module_Context *ctxt = data;
953 E_PackageKit_Transaction_Func func;
954 Eldbus_Proxy *proxy;
955 Eldbus_Object *obj;
956 Eina_Bool ret;
957
958 if (eldbus_message_error_get(msg, &error, &error_msg))
959 {
960 _store_error(ctxt, error_msg);
961 return;
962 }
963
964 if (PKITV07)
965 ret = eldbus_message_arguments_get(msg, "s", &trans_path);
966 else
967 ret = eldbus_message_arguments_get(msg, "o", &trans_path);
968 if (!ret)
969 {
970 _store_error(ctxt, "could not get transaction path");
971 return;
972 }
973
974 // monitor the "Percentage" property to update the progress bar
975 obj = eldbus_object_get(ctxt->conn, "org.freedesktop.PackageKit", trans_path);
976 proxy = eldbus_proxy_get(obj, "org.freedesktop.DBus.Properties");
977 eldbus_proxy_signal_handler_add(proxy, "PropertiesChanged",
978 _signal_transaction_props_changed_cb, ctxt);
979
980 // call the operation function
981 func = eldbus_pending_data_get(pending, "func");
982 func(ctxt, trans_path);
983
984 // update all the faces
985 packagekit_icon_update(ctxt, EINA_TRUE);
986 packagekit_all_popups_update(ctxt, EINA_FALSE);
987 }
988
989 void
packagekit_create_transaction_and_exec(E_PackageKit_Module_Context * ctxt,E_PackageKit_Transaction_Func func)990 packagekit_create_transaction_and_exec(E_PackageKit_Module_Context *ctxt,
991 E_PackageKit_Transaction_Func func)
992 {
993 Eldbus_Pending *pending;
994
995 //DBG("PKGKIT: Version: %d.%d.%d", ctxt->v_maj, ctxt->v_min, ctxt->v_mic);
996
997 if (ctxt->transaction)
998 {
999 WRN("PKGKIT: Another transaction in progress...");
1000 return;
1001 }
1002
1003 pending = eldbus_proxy_call(ctxt->packagekit,
1004 PKITV07 ? "GetTid" : "CreateTransaction",
1005 _transaction_created_cb, ctxt, -1, "");
1006 if (!pending)
1007 {
1008 _store_error(ctxt, "could not call CreateTransaction()");
1009 return;
1010 }
1011 eldbus_pending_data_set(pending, "func", func);
1012 }
1013
1014
1015 /* PackageKit DBus */
1016 static void
_signal_updates_changed_cb(void * data,const Eldbus_Message * msg EINA_UNUSED)1017 _signal_updates_changed_cb(void *data, const Eldbus_Message *msg EINA_UNUSED)
1018 {
1019 E_PackageKit_Module_Context *ctxt = data;
1020
1021 packagekit_create_transaction_and_exec(ctxt, packagekit_get_updates);
1022 }
1023
1024 static void
_iterate_dict(void * data,const void * key,Eldbus_Message_Iter * var)1025 _iterate_dict(void *data, const void *key, Eldbus_Message_Iter *var)
1026 {
1027 E_PackageKit_Module_Context *ctxt = data;
1028
1029 if (!strcmp(key, "VersionMajor"))
1030 eldbus_message_iter_arguments_get(var, "u", &(ctxt->v_maj));
1031 else if (!strcmp(key, "VersionMinor"))
1032 eldbus_message_iter_arguments_get(var, "u", &(ctxt->v_min));
1033 else if (!strcmp(key, "VersionMicro"))
1034 eldbus_message_iter_arguments_get(var, "u", &(ctxt->v_mic));
1035 else return;
1036
1037 if ((ctxt->v_maj != -1) && (ctxt->v_min != -1) && (ctxt->v_mic != -1))
1038 packagekit_create_transaction_and_exec(ctxt, packagekit_get_updates);
1039 }
1040
1041 static void
_prop_get_cb(void * data,const Eldbus_Message * msg,Eldbus_Pending * pending EINA_UNUSED)1042 _prop_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
1043 {
1044 E_PackageKit_Module_Context *ctxt = data;
1045 Eldbus_Message_Iter *array;
1046 const char *error, *error_msg;
1047
1048 if (eldbus_message_error_get(msg, &error, &error_msg))
1049 {
1050 _store_error(ctxt, error_msg);
1051 return;
1052 }
1053 if (!eldbus_message_arguments_get(msg, "a{sv}", &array))
1054 {
1055 _store_error(ctxt, "could not get arguments (a{sv})");
1056 return;
1057 }
1058 eldbus_message_iter_dict_iterate(array, "sv", _iterate_dict, ctxt);
1059 }
1060
1061 Eina_Bool
packagekit_dbus_connect(E_PackageKit_Module_Context * ctxt)1062 packagekit_dbus_connect(E_PackageKit_Module_Context *ctxt)
1063 {
1064 Eldbus_Object *obj;
1065
1066 //DBG("PKGKIT: dbus_init()");
1067
1068 ctxt->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
1069 if (!ctxt->conn)
1070 {
1071 _store_error(ctxt, "could not connect to system bus");
1072 return EINA_FALSE;
1073 }
1074
1075 obj = eldbus_object_get(ctxt->conn, "org.freedesktop.PackageKit",
1076 "/org/freedesktop/PackageKit");
1077 ctxt->packagekit = eldbus_proxy_get(obj, "org.freedesktop.PackageKit");
1078 if (!ctxt->packagekit)
1079 {
1080 _store_error(ctxt, "could not connect to PackageKit");
1081 return EINA_FALSE;
1082 }
1083
1084 eldbus_proxy_property_get_all(ctxt->packagekit, _prop_get_cb, ctxt);
1085 eldbus_proxy_signal_handler_add(ctxt->packagekit, "UpdatesChanged",
1086 _signal_updates_changed_cb, ctxt);
1087
1088 return EINA_TRUE;
1089 }
1090
1091 void
packagekit_dbus_disconnect(E_PackageKit_Module_Context * ctxt)1092 packagekit_dbus_disconnect(E_PackageKit_Module_Context *ctxt)
1093 {
1094 Eldbus_Object *obj;
1095
1096 //DBG("PKGKIT: dbus_shutdown()");
1097
1098 if (ctxt->transaction)
1099 {
1100 // TODO abort the transaction ???
1101 obj = eldbus_proxy_object_get(ctxt->transaction);
1102 E_FREE_FUNC(ctxt->transaction, eldbus_proxy_unref);
1103 E_FREE_FUNC(obj, eldbus_object_unref);
1104 }
1105
1106 obj = eldbus_proxy_object_get(ctxt->packagekit);
1107 E_FREE_FUNC(ctxt->packagekit, eldbus_proxy_unref);
1108 E_FREE_FUNC(obj, eldbus_object_unref);
1109
1110 eldbus_connection_unref(ctxt->conn);
1111 }
1112