pkit gadget: add ability to install updated directly from the gadget !

You can install all updates or select the packages you like.

The update work without asking any password, if it doesn't works check the
org.freedesktop.packagekit.system-update Polkit permission

(work out-of-the-box on Arch Linux, just install packagekit)
This commit is contained in:
Davide Andreoli 2017-08-12 19:28:16 +02:00
parent fcd271dd1b
commit ef8cc77790
2 changed files with 198 additions and 8 deletions

View File

@ -63,6 +63,39 @@ _update_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
packagekit_create_transaction_and_exec(inst->ctxt, packagekit_refresh_cache);
}
static void
_install_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event EINA_UNUSED)
{
E_PackageKit_Instance *inst = data;
E_PackageKit_Package *pkg;
const Eina_List *selected;
Elm_Genlist_Item *item;
Eina_List *l;
selected = elm_genlist_selected_items_get(inst->popup_genlist);
if (!selected)
{
// nothing selected, update all packages
EINA_LIST_FOREACH(inst->ctxt->packages, l, pkg)
pkg->to_be_installed = EINA_TRUE;
}
else
{
// only updated selected packages
EINA_LIST_FOREACH(inst->ctxt->packages, l, pkg)
pkg->to_be_installed = EINA_FALSE;
EINA_LIST_FOREACH((Eina_List*)selected, l, item)
{
pkg = elm_object_item_data_get(item);
pkg->to_be_installed = EINA_TRUE;
}
}
packagekit_create_transaction_and_exec(inst->ctxt, packagekit_update_packages);
packagekit_popup_del(inst);
}
static void
_run_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event EINA_UNUSED)
@ -81,14 +114,18 @@ _run_button_cb(void *data, Evas_Object *obj EINA_UNUSED,
}
void
packagekit_popup_update(E_PackageKit_Instance *inst)
packagekit_popup_update(E_PackageKit_Instance *inst, Eina_Bool rebuild_list)
{
E_PackageKit_Module_Context *ctxt = inst->ctxt;
E_PackageKit_Package *pkg;
const Eina_List *selected;
unsigned num_updates = 0;
char buf[1024];
Eina_List *l;
if (rebuild_list)
elm_genlist_clear(inst->popup_genlist);
if (ctxt->error)
{
elm_object_text_set(inst->popup_label, _("No information available"));
@ -104,16 +141,52 @@ packagekit_popup_update(E_PackageKit_Instance *inst)
EINA_LIST_FOREACH(ctxt->packages, l, pkg)
{
elm_genlist_item_append(inst->popup_genlist, inst->popup_genlist_itc,
pkg, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
if (rebuild_list)
elm_genlist_item_append(inst->popup_genlist, inst->popup_genlist_itc,
pkg, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
num_updates++;
}
// update title and error lables
if (num_updates >= 1)
snprintf(buf, sizeof(buf), P_("One update available", "%d updates available", num_updates), num_updates);
else
snprintf(buf, sizeof(buf), _("Your system is updated"));
elm_object_text_set(inst->popup_label, buf);
elm_object_text_set(inst->popup_error_label, "");
// update the status of the install button
selected = elm_genlist_selected_items_get(inst->popup_genlist);
if (num_updates < 1)
{
elm_object_text_set(inst->popup_install_button, _("Nothing to do"));
elm_object_disabled_set(inst->popup_install_button, EINA_TRUE);
}
else if ((selected == NULL) || (eina_list_count(selected) == 0))
{
elm_object_text_set(inst->popup_install_button,
_("Install all available updates"));
elm_object_disabled_set(inst->popup_install_button, EINA_FALSE);
}
else if (eina_list_count(selected) > 0)
{
snprintf(buf, sizeof(buf), P_("Install the selected update",
"Install %d selected updates",
eina_list_count(selected)),
eina_list_count(selected));
elm_object_text_set(inst->popup_install_button, buf);
elm_object_disabled_set(inst->popup_install_button, EINA_FALSE);
}
}
void
packagekit_all_popups_update(E_PackageKit_Module_Context *ctxt)
{
E_PackageKit_Instance *inst;
Eina_List *l;
EINA_LIST_FOREACH(ctxt->instances, l, inst)
packagekit_popup_update(inst, EINA_TRUE);
}
static void
@ -217,6 +290,13 @@ _gl_item_content_get(void *data, Evas_Object *obj, const char *part)
return NULL;
}
static void
_genlist_selunsel_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event EINA_UNUSED)
{
packagekit_popup_update(data, EINA_FALSE);
}
void
packagekit_popup_new(E_PackageKit_Instance *inst)
{
@ -275,17 +355,25 @@ packagekit_popup_new(E_PackageKit_Instance *inst)
elm_genlist_multi_select_set(li, EINA_TRUE);
E_EXPAND(li);
E_FILL(li);
evas_object_smart_callback_add(li, "selected", _genlist_selunsel_cb, inst);
evas_object_smart_callback_add(li, "unselected", _genlist_selunsel_cb, inst);
elm_table_pack(table, li, 0, 1, 2, 1);
evas_object_show(li);
bt = inst->popup_install_button = elm_button_add(table);
evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, 0.0);
evas_object_smart_callback_add(bt, "clicked", _install_button_cb, inst);
elm_table_pack(table, bt, 0, 2, 2, 1);
evas_object_show(bt);
bt = elm_button_add(table);
evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, 0.0);
elm_object_text_set(bt, _("Run the package manager"));
evas_object_smart_callback_add(bt, "clicked", _run_button_cb, inst);
elm_table_pack(table, bt, 0, 2, 2, 1);
elm_table_pack(table, bt, 0, 3, 2, 1);
evas_object_show(bt);
packagekit_popup_update(inst);
packagekit_popup_update(inst, EINA_TRUE);
e_gadcon_popup_content_set(inst->popup, table);
e_comp_object_util_autoclose(inst->popup->comp_object,
@ -309,6 +397,7 @@ packagekit_popup_del(E_PackageKit_Instance *inst)
}
/* DBus PackageKit */
static void
_store_error(E_PackageKit_Module_Context *ctxt, const char *err)
{
@ -318,10 +407,9 @@ _store_error(E_PackageKit_Module_Context *ctxt, const char *err)
else
ctxt->error = eina_stringshare_add(err);
packagekit_icon_update(ctxt, EINA_FALSE);
packagekit_all_popups_update(ctxt);
}
/* RefreshCache() */
static void
null_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
@ -332,6 +420,7 @@ null_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUS
_store_error(ctxt, error_msg);
}
/* RefreshCache() */
static void
signal_repo_detail_cb(void *data, const Eldbus_Message *msg)
{ /* RepoDetail ('s'repo_id, 's'description, 'b'enabled) */
@ -430,6 +519,7 @@ _signal_package_cb(void *data, const Eldbus_Message *msg)
if (num_elements >= 2)
{
E_PackageKit_Package *pkg = E_NEW(E_PackageKit_Package, 1);
pkg->pkg_id = eina_stringshare_add(pkg_id);
pkg->name = eina_stringshare_add(splitted[0]);
pkg->version = eina_stringshare_add(splitted[1]);
pkg->summary = eina_stringshare_add(summary);
@ -475,6 +565,7 @@ _signal_finished_cb(void *data, const Eldbus_Message *msg)
//DBG("PKGKIT: PackageFinished");
packagekit_icon_update(ctxt, EINA_FALSE);
packagekit_all_popups_update(ctxt);
}
void
@ -503,6 +594,7 @@ packagekit_get_updates(E_PackageKit_Module_Context *ctxt, const char *transactio
EINA_LIST_FREE(ctxt->packages, pkg)
{
E_FREE_FUNC(pkg->pkg_id, eina_stringshare_del);
E_FREE_FUNC(pkg->name, eina_stringshare_del);
E_FREE_FUNC(pkg->version, eina_stringshare_del);
E_FREE_FUNC(pkg->summary, eina_stringshare_del);
@ -510,6 +602,92 @@ packagekit_get_updates(E_PackageKit_Module_Context *ctxt, const char *transactio
}
/* UpdatePackages */
static void
_signal_update_error_code_cb(void *data, const Eldbus_Message *msg)
{ /* ErrorCode ('u'code, 's'details) */
const char *error, *error_msg, *details;
E_PackageKit_Module_Context *ctxt = data;
Eina_Bool ret;
int err_code;
if (eldbus_message_error_get(msg, &error, &error_msg))
{
_store_error(ctxt, error_msg);
return;
}
ret = eldbus_message_arguments_get(msg, "us", &err_code, &details);
if (!ret)
{
_store_error(ctxt, "could not get error code arguments");
return;
}
if (details)
_store_error(ctxt, details);
}
static void
_signal_update_finished_cb(void *data, const Eldbus_Message *msg)
{ /* Finished ('u'exit, 'u'runtime) */
const char *error, *error_msg;
E_PackageKit_Module_Context *ctxt = data;
if (eldbus_message_error_get(msg, &error, &error_msg))
_store_error(ctxt, error_msg);
else
E_FREE_FUNC(ctxt->error, eina_stringshare_del);
Eldbus_Object *obj = eldbus_proxy_object_get(ctxt->transaction);
E_FREE_FUNC(ctxt->transaction, eldbus_proxy_unref);
E_FREE_FUNC(obj, eldbus_object_unref);
}
void
packagekit_update_packages(E_PackageKit_Module_Context *ctxt, const char *transaction)
{
Eldbus_Object *obj;
Eldbus_Proxy *proxy;
Eldbus_Message *msg;
Eldbus_Message_Iter *iter, *array_of_string;
Eldbus_Pending *pending;
E_PackageKit_Package *pkg;
Eina_List *l;
fprintf(stderr, "PKIT: UpdatePackages (t:%s)\n", transaction);
obj = eldbus_object_get(ctxt->conn, "org.freedesktop.PackageKit", transaction);
proxy = eldbus_proxy_get(obj, "org.freedesktop.PackageKit.Transaction");
msg = eldbus_proxy_method_call_new(proxy, "UpdatePackages");
iter = eldbus_message_iter_get(msg);
eldbus_message_iter_arguments_append(iter, "tas",
PK_TRANSACTION_FLAG_ENUM_ONLY_TRUSTED,
&array_of_string);
EINA_LIST_FOREACH(ctxt->packages, l, pkg)
{
if (pkg->to_be_installed)
{
DBG("Install: %s %s", pkg->pkg_id, pkg->version);
eldbus_message_iter_arguments_append(array_of_string, "s", pkg->pkg_id);
}
}
eldbus_message_iter_container_close(iter, array_of_string);
pending = eldbus_proxy_send(proxy, msg, null_cb, ctxt, -1);
if (!pending)
{
_store_error(ctxt, "could not call UpdatePackages()");
return;
}
// TODO: monitor the PropertiesChanged for "Percentage" on the Transaction
// object and show a progress bar!
eldbus_proxy_signal_handler_add(proxy, "ErrorCode", _signal_update_error_code_cb, ctxt);
eldbus_proxy_signal_handler_add(proxy, "Finished", _signal_update_finished_cb, ctxt);
ctxt->transaction = proxy;
}
/* CreateTransaction() */
static void
_transaction_created_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)

View File

@ -7,6 +7,14 @@
#define PKITV07 (ctxt->v_maj == 0) && (ctxt->v_min == 7)
#define PKITV08 (ctxt->v_maj == 0) && (ctxt->v_min == 8)
// PackageKit dbus interface contains bitfield constants which
// aren't introspectable. we define here. still cannot find the proper doc!
#define PK_PROVIDES_ANY 1
#define PK_FILTER_ENUM_NOT_INSTALLED 1 << 3
#define PK_FILTER_ENUM_NEWEST 1 << 16
#define PK_FILTER_ENUM_ARCH 1 << 18
#define PK_TRANSACTION_FLAG_ENUM_ONLY_TRUSTED 1 << 1
typedef enum {
PK_INFO_ENUM_UNKNOWN,
PK_INFO_ENUM_INSTALLED,
@ -72,16 +80,19 @@ typedef struct _E_PackageKit_Instance
E_Gadcon_Popup *popup;
Evas_Object *popup_label;
Evas_Object *popup_error_label;
Evas_Object *popup_install_button;
Evas_Object *popup_genlist;
Elm_Genlist_Item_Class *popup_genlist_itc;
} E_PackageKit_Instance;
typedef struct _E_PackageKit_Package
{
const char *pkg_id;
const char *name;
const char *summary;
const char *version;
PackageKit_Package_Info info;
Eina_Bool to_be_installed;
} E_PackageKit_Package;
@ -95,10 +106,11 @@ void packagekit_create_transaction_and_exec(E_PackageKit_Module_Context *ct
E_PackageKit_Transaction_Func func);
void packagekit_get_updates(E_PackageKit_Module_Context *ctxt, const char *transaction);
void packagekit_refresh_cache(E_PackageKit_Module_Context *ctxt, const char *transaction);
void packagekit_update_packages(E_PackageKit_Module_Context *ctxt, const char *transaction);
void packagekit_icon_update(E_PackageKit_Module_Context *ctxt, Eina_Bool working);
void packagekit_popup_new(E_PackageKit_Instance *inst);
void packagekit_popup_del(E_PackageKit_Instance *inst);
void packagekit_popup_update(E_PackageKit_Instance *inst);
void packagekit_popup_update(E_PackageKit_Instance *inst, Eina_Bool rebuild_list);
#endif