package-update-indicator-5/README010064400017500001750000000121771353220474000154160ustar00gbergberpackage-update-indicator ======================== Description ----------- The package-update-indicator utility regularly checks for software updates and notifies the user about available updates using desktop notifications and either a status notifier icon or a system tray icon. Build Instructions ------------------ package-update-indicator requires a POSIX:2004 compatible operating system, it has been tested to work on Linux distributions. The following tools and shared libraries are required to build package-update-indicator: - GNU make 3.81 or later - pkg-config - GNU gettext 0.19 or later - GNU or BSD install - GLib version 2.48 or later - GTK+ version 3.18 or later - libappindicator 12.10.0 or later - PackageKit-glib2 0.8.17 or later - upower-glib 0.99.0 or later - polkit 0.105 or later - the xsltproc tool from libxml2 Before building package-update-indicator check the commented macros in the Makefile for any macros you may need to override depending on the used toolchain and operating system. By default the "update-command" setting is empty which means users will not be offered to install updates from a notification or the indicator menu. Distribution vendors may override this or any other default setting by installing a vendor override file alongside the schema file. An example for is distributed with package-update-indicator, see the file "examples/10_vendor_update_command.gschema.override.example". For details on how to install a vendor override file see the manual page for glib-compile-schemas. By default, all files will be installed under the "/usr/local" directory, a different installation path prefix can be set via the `prefix` macro. In addition, a second path prefix can be specified via the `DESTDIR` macro which will be prepended to any path, incuding the `prefix` macro path prefix. In contrast to `prefix`, the path specified via the `DESTDIR` macro will only be prepended to paths during installation and not be used for constructing internal paths. The following instructions assume that `make` is GNU make, on some platforms it may be installed under a different name or a non-default path. In order to start the build process run `make all`. After a successful build, run `make install` to install the program, any associated data files and the documentation. Previously built binaries, object files, generated data files and documentation can be removed by running `make clean`, any additional, generated files which are not removed by the `clean` target can be removed by running `make clobber`. Contact ------- Please send any feedback, translations or bug reports via email to . Bug Reports ----------- When sending bug reports, please always mention the exact version of package-update-indicator with which the issue occurs as well as the version of the operating system you are using and make sure that you provide sufficient information to reproduce the issue and include any input, output, any error messages. In case of build issues, please also specify the implementations and versions of the tools and shared libraries used to build the program, in particular the compiler. In case of crashes, please generate a stack trace with a suitable debugger such as gdb, lldb, dbx, or debug after a crash has occurred either by examining the resulting core file or by running the program from the debugger and attach it to the bug report. In order to generate a meaningful stack trace the program as well as any dynamically linked libraries need to be built with debugging information, see the documentation of the used compiler for the required compiler flags. If any of the dynamically linked shared libraries do not contain debugging information, please either install debugging information for these libraries using mechanisms provided by your operating system or rebuild the libraries accordingly. Please refer to the documentation of the debugger for detailed instructions on generating backtraces. License ------- Except otherwise noted, all files are Copyright (C) 2018 Guido Berhoerster and distributed under the following license terms: Copyright (C) 2018 Guido Berhoerster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package-update-indicator-5/pui-settings.h010064400017500001750000000024121353220474000173310ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PUI_SETTINGS_H #define PUI_SETTINGS_H #include GSettings * pui_settings_new(void); #endif /* !PUI_SETTINGS_H */ package-update-indicator-5/package-update-indicator-prefs.1.xml010064400017500001750000000073051353220474000233560ustar00gbergber Guido Berhoerster guido+pui@berhoerster.name 17 June, 2018 package-update-indicator-prefs 1 User Commands package-update-indicator-prefs edit preferences for package-update-indicator package-update-indicator-prefs Description The package-update-indicator-prefs utility can be used to edit the preferences for package-update-indicator. Preferences Cache refresh interval The interval in which package metadata is refreshed. Update installer command The command for installing updates. Use mobile connection Whether to use a mobile connection for refreshing the package cache. Exit Status The following exit values are returned: 0 Command successfully executed. 1 An unspecified error has occured. 2 Invalid command line options were specified. See Also package-update-indicator 1 package-update-indicator-5/package-update-indicator-prefs.c010064400017500001750000000034061353220474000226370ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "pui-prefs-application.h" int main(int argc, char *argv[]) { int status; PuiPrefsApplication *application; bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); setlocale(LC_ALL, ""); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); g_set_application_name(_("Package Update Indicator Preferences")); gtk_init(&argc, &argv); application = pui_prefs_application_new(); status = g_application_run(G_APPLICATION(application), argc, argv); g_object_unref(application); exit(status); } package-update-indicator-5/pui-backend.h010064400017500001750000000036771353220474000170760ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PUI_BACKEND_H #define PUI_BACKEND_H #include #include G_BEGIN_DECLS #define PUI_TYPE_BACKEND (pui_backend_get_type()) #define PUI_BACKEND_ERROR (pui_backend_error_quark()) G_DECLARE_FINAL_TYPE(PuiBackend, pui_backend, PUI, BACKEND, GObject) enum { PUI_BACKEND_ERROR_GET_UPDATES_NOT_IMPLEMENTED }; typedef enum { PUI_RESTART_NONE, PUI_RESTART_SESSION, PUI_RESTART_SYSTEM, PUI_RESTART_LAST } PuiRestart; GQuark pui_backend_error_quark(void); void pui_backend_new_async(GCancellable *, GAsyncReadyCallback, gpointer); PuiBackend * pui_backend_new_finish(GAsyncResult *, GError **); void pui_backend_set_proxy(PuiBackend *, const gchar *, const gchar *, const gchar *, const gchar *, const gchar *, const gchar *); G_END_DECLS #endif /* !PUI_BACKEND_H */ package-update-indicator-5/pui-backend.c010064400017500001750000000556451353220474000170730ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include "pui-common.h" #include "pui-backend.h" #include "pui-get-updates.h" #include "pui-types.h" #define LOW_BATTERY_THRESHOLD 10.0 /* % */ #define UPDATES_CHANGED_UNBLOCK_DELAY 4 /* s */ struct _PuiBackend { GObject parent_instance; PkControl *pk_control; GCancellable *cancellable; PkClient *pk_client; PkTransactionList *transaction_list; UpClient *up_client; UpDevice *up_device; gchar *proxy_http; gchar *proxy_https; gchar *proxy_ftp; gchar *proxy_socks; gchar *no_proxy; gchar *pac; gint64 last_check; PkNetworkEnum network_state; gboolean inhibited; gboolean is_battery_low; guint check_id; guint unblock_updates_changed_id; guint refresh_interval; gboolean use_mobile_connection; guint important_updates; guint normal_updates; PuiRestart restart_type; }; static void pui_backend_async_initable_iface_init(gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE(PuiBackend, pui_backend, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_ASYNC_INITABLE, pui_backend_async_initable_iface_init)) enum { STATE_CHANGED, RESTART_REQUIRED, SIGNAL_LAST }; enum { PROP_0, PROP_IMPORTANT_UPDATES, PROP_NORMAL_UPDATES, PROP_RESTART_TYPE, PROP_REFRESH_INTERVAL, PROP_USE_MOBILE_CONNECTION, PROP_LAST }; static guint signals[SIGNAL_LAST] = { 0 }; static GParamSpec *properties[PROP_LAST] = { NULL }; static gboolean periodic_check(gpointer); static void on_updates_changed(PkControl *, gpointer); GQuark pui_backend_error_quark(void) { return (g_quark_from_static_string("pui-backend-error-quark")); } static void process_pk_package(gpointer data, gpointer user_data) { PkPackage *package = data; PuiBackend *self = user_data; PkInfoEnum type_info = pk_package_get_info(package); switch (type_info) { case PK_INFO_ENUM_LOW: /* FALLTHROUGH */ case PK_INFO_ENUM_ENHANCEMENT: /* FALLTHROUGH */ case PK_INFO_ENUM_NORMAL: self->normal_updates++; break; case PK_INFO_ENUM_BUGFIX: /* FALLTHROUGH */ case PK_INFO_ENUM_IMPORTANT: /* FALLTHROUGH */ case PK_INFO_ENUM_SECURITY: self->important_updates++; break; default: break; } } static gboolean unblock_updates_changed(gpointer user_data) { PuiBackend *self = user_data; g_signal_handlers_unblock_by_func(self->pk_control, on_updates_changed, self); self->unblock_updates_changed_id = 0; return (G_SOURCE_REMOVE); } static void on_get_updates_finished(GObject *source_object, GAsyncResult *async_result, gpointer user_data) { PuiBackend *self = user_data; GPtrArray *package_list = NULL; GError *error = NULL; guint prev_normal_updates = self->normal_updates; guint prev_important_updates = self->important_updates; package_list = pui_get_updates_finish(async_result, &error); if (package_list == NULL) { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || g_error_matches(error, PUI_GET_UPDATES_ERROR, PUI_GET_UPDATES_ERROR_CANCELLED)) { /* cancelled */ g_debug("cancelled checking for updates"); } else { g_warning("failed to check for updates: %s", error->message); } g_error_free(error); goto out; } self->normal_updates = 0; self->important_updates = 0; g_ptr_array_foreach(package_list, process_pk_package, self); g_debug("normal updates: %u, important updates: %u", self->normal_updates, self->important_updates); if (self->normal_updates != prev_normal_updates) { g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_NORMAL_UPDATES]); } if (self->important_updates != prev_important_updates) { g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_IMPORTANT_UPDATES]); } if ((self->normal_updates != prev_normal_updates) || (self->important_updates != prev_important_updates)) { g_debug("emitting signal state-changed"); g_signal_emit(self, signals[STATE_CHANGED], 0); } /* last successful check */ self->last_check = g_get_monotonic_time(); out: g_clear_object(&self->cancellable); /* reschedule periodic check */ if (!self->inhibited) { self->check_id = g_timeout_add_seconds(PUI_CHECK_UPDATES_INTERVAL, periodic_check, self); } /* handle get-updates signals again after a short delay */ self->unblock_updates_changed_id = g_timeout_add_seconds(UPDATES_CHANGED_UNBLOCK_DELAY, unblock_updates_changed, self); if (package_list != NULL) { g_ptr_array_unref(package_list); } } static void run_check(PuiBackend *self, gboolean refresh_cache) { /* block any get-updates signals emitted when refreshing the cache */ if (self->unblock_updates_changed_id != 0) { /* still blocked */ g_source_remove(self->unblock_updates_changed_id); self->unblock_updates_changed_id = 0; } else { g_signal_handlers_block_by_func(self->pk_control, G_CALLBACK(on_updates_changed), self); } self->cancellable = g_cancellable_new(); pui_get_updates_async(self->pk_control, refresh_cache ? self->refresh_interval : G_MAXUINT, self->cancellable, on_get_updates_finished, self); /* next periodic check will be scheduled after completion */ self->check_id = 0; } static gboolean irregular_check(gpointer user_data) { PuiBackend *self = user_data; g_debug("running check"); run_check(self, FALSE); return (G_SOURCE_REMOVE); } static gboolean periodic_check(gpointer user_data) { PuiBackend *self = user_data; g_debug("running periodic check"); run_check(self, TRUE); return (G_SOURCE_REMOVE); } static void check_inhibit(PuiBackend *self) { gboolean inhibited; guint elapsed_time; guint remaining_time; inhibited = ((self->network_state == PK_NETWORK_ENUM_OFFLINE) || (!self->use_mobile_connection && (self->network_state == PK_NETWORK_ENUM_MOBILE)) || self->is_battery_low); if (self->inhibited == inhibited) { return; } self->inhibited = inhibited; if (inhibited) { /* cancel periodic checks */ if (self->check_id != 0) { g_source_remove(self->check_id); } /* cancel running operation */ if ((self->cancellable != NULL) && !g_cancellable_is_cancelled(self->cancellable)) { g_cancellable_cancel(self->cancellable); g_clear_object(&self->cancellable); } } else { /* schedule periodic checks when no longer inhibited */ elapsed_time = (g_get_monotonic_time() - self->last_check) / G_USEC_PER_SEC; /* * if more time that the check interval has passed since the * last check, schedule a check after a short delay, otherwise * wait until the interval has passed */ remaining_time = (elapsed_time < PUI_CHECK_UPDATES_INTERVAL) ? PUI_CHECK_UPDATES_INTERVAL - elapsed_time : PUI_STARTUP_DELAY; self->check_id = g_timeout_add_seconds(remaining_time, periodic_check, self); } } static void pui_backend_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PuiBackend *self = PUI_BACKEND(object); switch (property_id) { case PROP_REFRESH_INTERVAL: self->refresh_interval = g_value_get_uint(value); g_debug("property \"refresh-interval\" set to %u", self->refresh_interval); break; case PROP_USE_MOBILE_CONNECTION: self->use_mobile_connection = g_value_get_boolean(value); g_debug("property \"use-mobile-connection\" set to %s", self->use_mobile_connection ? "true" : "false"); check_inhibit(self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void pui_backend_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PuiBackend *self = PUI_BACKEND(object); switch (property_id) { case PROP_IMPORTANT_UPDATES: g_value_set_uint(value, self->important_updates); break; case PROP_NORMAL_UPDATES: g_value_set_uint(value, self->normal_updates); break; case PROP_RESTART_TYPE: g_value_set_enum(value, self->restart_type); break; case PROP_REFRESH_INTERVAL: g_value_set_uint(value, self->refresh_interval); break; case PROP_USE_MOBILE_CONNECTION: g_value_set_boolean(value, self->use_mobile_connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void pui_backend_dispose(GObject *object) { PuiBackend *self = PUI_BACKEND(object); if (self->check_id != 0) { g_source_remove(self->check_id); self->check_id = 0; } if (self->unblock_updates_changed_id != 0) { g_source_remove(self->unblock_updates_changed_id); self->unblock_updates_changed_id = 0; } if (self->transaction_list != NULL) { g_clear_object(&self->transaction_list); } if (self->pk_client != NULL) { g_clear_object(&self->pk_client); } if (self->cancellable != NULL) { g_cancellable_cancel(self->cancellable); g_clear_object(&self->cancellable); } if (self->pk_control != NULL) { g_clear_object(&self->pk_control); } if (self->up_device != NULL) { g_clear_object(&self->up_device); } if (self->up_client != NULL) { g_clear_object(&self->up_client); } G_OBJECT_CLASS(pui_backend_parent_class)->dispose(object); } static void pui_backend_finalize(GObject *object) { PuiBackend *self = PUI_BACKEND(object); g_free(self->proxy_http); g_free(self->proxy_https); g_free(self->proxy_ftp); g_free(self->proxy_socks); g_free(self->no_proxy); g_free(self->pac); G_OBJECT_CLASS(pui_backend_parent_class)->finalize(object); } static void pui_backend_class_init(PuiBackendClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->set_property = pui_backend_set_property; object_class->get_property = pui_backend_get_property; object_class->dispose = pui_backend_dispose; object_class->finalize = pui_backend_finalize; properties[PROP_IMPORTANT_UPDATES] = g_param_spec_uint("important-updates", "Important updates", "Number of available important updates", 0, G_MAXUINT, 0, G_PARAM_READABLE); properties[PROP_NORMAL_UPDATES] = g_param_spec_uint("normal-updates", "Normal updates", "Number of available normal updates", 0, G_MAXUINT, 0, G_PARAM_READABLE); properties[PROP_RESTART_TYPE] = g_param_spec_enum("restart-type", "Type of restart required", "The Type of restart required", PUI_TYPE_RESTART, PUI_RESTART_NONE, G_PARAM_READABLE); properties[PROP_REFRESH_INTERVAL] = g_param_spec_uint("refresh-interval", "Refresh interval", "Interval in seconds for refreshing the package cache", 0, G_MAXUINT, PUI_DEFAULT_REFRESH_INTERVAL, G_PARAM_READWRITE); properties[PROP_USE_MOBILE_CONNECTION] = g_param_spec_boolean("use-mobile-connection", "Whether to use a mobile connection", "Whether to use a mobile " "connection for refreshing the package cache", FALSE, G_PARAM_READWRITE); g_object_class_install_properties(object_class, PROP_LAST, properties); signals[STATE_CHANGED] = g_signal_new("state-changed", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); signals[RESTART_REQUIRED] = g_signal_new("restart-required", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); } static void pui_backend_init(PuiBackend *self) { self->pk_control = pk_control_new(); self->pk_client = pk_client_new(); self->inhibited = TRUE; self->up_client = up_client_new(); if (self->up_client) { self->up_device = up_client_get_display_device(self->up_client); } } static void on_get_properties_finished(GObject *object, GAsyncResult *result, gpointer user_data) { PkControl *control = PK_CONTROL(object); PuiBackend *self; GTask *task = user_data; GError *error = NULL; gchar *backend_name = NULL; PkBitfield roles = 0; gchar *roles_str = NULL; self = g_task_get_task_data(task); if (!pk_control_get_properties_finish(control, result, &error)) { g_task_return_error(task, error); goto out; } /* check whether the backend supports GetUpdates */ g_object_get(control, "backend-name", &backend_name, "roles", &roles, "network-state", &self->network_state, NULL); g_debug("backend: %s", backend_name); roles_str = pk_role_bitfield_to_string(roles); g_debug("roles: %s", roles_str); g_debug("network-state: %s", pk_network_enum_to_string(self->network_state)); if (!pk_bitfield_contain(roles, PK_ROLE_ENUM_GET_UPDATES)) { error = g_error_new(PUI_BACKEND_ERROR, PUI_BACKEND_ERROR_GET_UPDATES_NOT_IMPLEMENTED, "Getting updates is not implemented in the %s PackageKit " "backend", backend_name); g_task_return_error(task, error); goto out; } g_task_return_boolean(task, TRUE); out: g_free(roles_str); g_free(backend_name); g_object_unref(task); } static void on_notify_device_charge_percentage(UpDevice *device, GParamSpec *pspec, gpointer user_data) { PuiBackend *self = user_data; UpDeviceKind kind; gdouble percentage; g_object_get(device, "kind", &kind, "percentage", &percentage, NULL); if ((kind != UP_DEVICE_KIND_BATTERY) && (kind != UP_DEVICE_KIND_UPS)) { return; } g_debug("charge percentage changed: %.0f%%\n", percentage); if ((self->is_battery_low && (percentage > LOW_BATTERY_THRESHOLD)) || (!self->is_battery_low && (percentage < LOW_BATTERY_THRESHOLD))) { self->is_battery_low = !self->is_battery_low; check_inhibit(self); } } static void on_notify_network_state(PkControl *pk_control, GParamSpec *pspec, gpointer user_data) { PuiBackend *self = user_data; g_object_get(pk_control, "network-state", &self->network_state, NULL); g_debug("network state changed: %s", pk_network_enum_to_string(self->network_state)); check_inhibit(self); } static void on_updates_changed(PkControl *control, gpointer user_data) { PuiBackend *self = user_data; g_debug("package metatdata cache invalidated"); /* * schedule a check after a short delay so that a rapid succession of * signals is coalesced */ if (!self->inhibited) { if (self->check_id != 0) { g_source_remove(self->check_id); } self->check_id = g_timeout_add_seconds(PUI_UPDATES_CHANGED_DELAY, irregular_check, self); } } static void on_restart_schedule(PkControl *control, gpointer user_data) { PuiBackend *self = user_data; /* * do not restart package-update-indicator if a session or system * restart is required since that iformation would be lost across the * restart, rather keep running and risk errors when interacting with * a newer version of the PackageKit daemon */ if (self->restart_type > PUI_RESTART_NONE) { return; } g_debug("emitting signal restart-required"); g_signal_emit(self, signals[RESTART_REQUIRED], 0); } static void on_transaction_adopt_finish(GObject *source_object, GAsyncResult *result, gpointer user_data) { PuiBackend *self = user_data; PkClient *pk_client = PK_CLIENT(source_object); PkResults *results; GError *error = NULL; PkRestartEnum restart; results = pk_client_generic_finish(pk_client, result, &error); if (results == NULL) { g_warning("failed to get transaction results: %s", error->message); g_error_free(error); goto out; } /* check if transaction requires a restart */ restart = pk_results_get_require_restart_worst(results); switch (restart) { case PK_RESTART_ENUM_SESSION: /* FALLTHROUGH */ case PK_RESTART_ENUM_SECURITY_SESSION: if (self->restart_type < PUI_RESTART_SESSION) { self->restart_type = PUI_RESTART_SESSION; g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_RESTART_TYPE]); g_signal_emit(self, signals[STATE_CHANGED], 0); } break; case PK_RESTART_ENUM_SYSTEM: /* FALLTHROUGH */ case PK_RESTART_ENUM_SECURITY_SYSTEM: if (self->restart_type < PUI_RESTART_SYSTEM) { self->restart_type = PUI_RESTART_SYSTEM; g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_RESTART_TYPE]); g_signal_emit(self, signals[STATE_CHANGED], 0); } break; default: /* do nothing */ break; } g_debug("transaction finished, required restart: %s", pk_restart_enum_to_string(restart)); out: if (results != NULL) { g_object_unref(results); } } static void on_transaction_list_added(PkTransactionList *transaction_list, const gchar *transaction_id, gpointer user_data) { PuiBackend *self = user_data; /* adopt transaction in order to monitor it for restart requirements */ pk_client_adopt_async(self->pk_client, transaction_id, NULL, NULL, NULL, on_transaction_adopt_finish, user_data); } static void pui_backend_init_async(GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { PuiBackend *self = PUI_BACKEND(initable); GTask *task; task = g_task_new(G_OBJECT(initable), cancellable, callback, user_data); g_task_set_priority(task, io_priority); g_task_set_task_data(task, g_object_ref(self), (GDestroyNotify)g_object_unref); pk_control_get_properties_async(self->pk_control, cancellable, on_get_properties_finished, task); } static gboolean pui_backend_init_finish(GAsyncInitable *initable, GAsyncResult *result, GError **errorp) { PuiBackend *self = PUI_BACKEND(initable); GTask *task = G_TASK(result); UpDeviceKind kind; gdouble percentage; if (!g_task_propagate_boolean(task, errorp)) { return (FALSE); } if (self->up_device != NULL) { /* get the kind of device and charge percentage */ g_object_get(self->up_device, "kind", &kind, "percentage", &percentage, NULL); if ((kind == UP_DEVICE_KIND_BATTERY) || (kind == UP_DEVICE_KIND_UPS)) { self->is_battery_low = (percentage < LOW_BATTERY_THRESHOLD); } /* get notification if the charge percentage changes */ g_signal_connect(self->up_device, "notify::percentage", G_CALLBACK(on_notify_device_charge_percentage), self); } /* get notification when the network state changes */ g_signal_connect(self->pk_control, "notify::network-state", G_CALLBACK(on_notify_network_state), self); /* get notifications when the package metatdata cache is invalidated */ g_signal_connect(self->pk_control, "updates-changed", G_CALLBACK(on_updates_changed), self); /* get notifications when an application restart is required */ g_signal_connect(self->pk_control, "restart-schedule", G_CALLBACK(on_restart_schedule), self); /* get notifications when a transactions are added */ self->transaction_list = pk_transaction_list_new(); g_signal_connect(self->transaction_list, "added", G_CALLBACK(on_transaction_list_added), self); check_inhibit(self); return (TRUE); } static void pui_backend_async_initable_iface_init(gpointer g_iface, gpointer iface_data) { GAsyncInitableIface *iface = g_iface; iface->init_async = pui_backend_init_async; iface->init_finish = pui_backend_init_finish; } void pui_backend_new_async(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async(PUI_TYPE_BACKEND, G_PRIORITY_DEFAULT, cancellable, callback, user_data, NULL); } PuiBackend * pui_backend_new_finish(GAsyncResult *result, GError **errorp) { GObject *object; GObject *source_object; source_object = g_async_result_get_source_object(result); object = g_async_initable_new_finish(G_ASYNC_INITABLE(source_object), result, errorp); g_object_unref(source_object); return ((object != NULL) ? PUI_BACKEND(object) : NULL); } static void on_set_proxy_finished(GObject *source_object, GAsyncResult *result, gpointer user_data) { PuiBackend *self = user_data; GError *error = NULL; if (!pk_control_set_proxy_finish(self->pk_control, result, &error)) { g_warning("failed to set proxies: %s", error->message); g_error_free(error); } } static void on_polkit_permission_finished(GObject *source_object, GAsyncResult *result, gpointer user_data) { PuiBackend *self = user_data; GPermission *permission; GError *error = NULL; permission = polkit_permission_new_finish(result, &error); if (permission == NULL) { g_warning("failed to create PolKit permission for setting the " "network proxies: %s", error->message); g_error_free(error); return; } if (!g_permission_get_allowed(permission)) { /* setting the proxy requires authentication or is disallowed */ g_debug("setting the network proxy is not allowed"); return; } g_debug("setting HTTP proxy to \"%s\"", (self->proxy_http != NULL) ? self->proxy_http : "(null)"); g_debug("setting HTTPS proxy to \"%s\"", (self->proxy_https != NULL) ? self->proxy_https : "(null)"); g_debug("setting FTP proxy to \"%s\"", (self->proxy_ftp != NULL) ? self->proxy_ftp : "(null)"); g_debug("setting SOCKS proxy to \"%s\"", (self->proxy_socks != NULL) ? self->proxy_socks : "(null)"); g_debug("setting the list of download IPs which should not go through " "a proxy to \"%s\"", (self->no_proxy != NULL) ? self->no_proxy : "(null)"); g_debug("setting the PAC string to \"%s\"", (self->pac != NULL) ? self->pac : "(null)"); pk_control_set_proxy2_async(self->pk_control, self->proxy_http, self->proxy_https, self->proxy_ftp, self->proxy_socks, self->no_proxy, self->pac, NULL, on_set_proxy_finished, self); } void pui_backend_set_proxy(PuiBackend *self, const gchar *proxy_http, const gchar *proxy_https, const gchar *proxy_ftp, const gchar *proxy_socks, const gchar *no_proxy, const gchar *pac) { g_free(self->proxy_http); self->proxy_http = (proxy_http != NULL) ? g_strdup(proxy_http) : NULL; g_free(self->proxy_https); self->proxy_https = (proxy_https != NULL) ? g_strdup(proxy_https) : NULL; g_free(self->proxy_ftp); self->proxy_ftp = (proxy_ftp != NULL) ? g_strdup(proxy_ftp) : NULL; g_free(self->proxy_socks); self->proxy_socks = (proxy_socks != NULL) ? g_strdup(proxy_socks) : NULL; g_free(self->no_proxy); self->no_proxy = (no_proxy != NULL) ? g_strdup(no_proxy) : NULL; g_free(self->pac); self->pac = (pac != NULL) ? g_strdup(pac) : NULL; polkit_permission_new("org.freedesktop.packagekit." "system-network-proxy-configure", NULL, NULL, on_polkit_permission_finished, self); } package-update-indicator-5/deps.sed010064400017500001750000000012451353220474000161600ustar00gbergber/^[^:]\{1,\}:.*\\$/{ h s/\([^:]\{1,\}:\).*/\1/ x s/[^:]\{1,\}:// } /\\$/,/^$/bgen /\\$/,/[^\\]$/{ :gen s/[[:blank:]]*\\$// s/^[[:blank:]]*// G s/\(.*\)\n\(.*\)/\2 \1/ } /^[^:]\{1,\}:[[:blank:]]*$/d /^[^:]\{1,\}\.o:/{ s/[[:blank:]]*[^[:blank:]]\{1,\}\.[cC][[:blank:]]*/ /g s/[[:blank:]]*[^[:blank:]]\{1,\}\.[cC]$//g s/[[:blank:]]*[^[:blank:]]\{1,\}\.cc[[:blank:]]*/ /g s/[[:blank:]]*[^[:blank:]]\{1,\}\.cc$//g s/[[:blank:]]*[^[:blank:]]\{1,\}\.cpp[[:blank:]]*/ /g s/[[:blank:]]*[^[:blank:]]\{1,\}\.cpp$//g /^[^:]\{1,\}:[[:blank:]]*$/d s/^\([^:]\{1,\}\)\.o[[:blank:]]*:[[:blank:]]*\(.*\)/\1.d: $(wildcard \2)\ &/ } package-update-indicator-5/pui-application.c010064400017500001750000000526431353220474000200020ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #ifndef HAVE_AYATANA_APPINDICATOR #include #else /* !HAVE_AYATANA_APPINDICATOR */ #include #endif /* !HAVE_AYATANA_APPINDICATOR */ #include #include #include "pui-application.h" #include "pui-backend.h" #include "pui-common.h" #include "pui-settings.h" #include "pui-types.h" struct _PuiApplication { GApplication parent_instance; GSettings *settings; GCancellable *cancellable; PuiBackend *backend; AppIndicator *indicator; GtkWidget *about_dialog; GIcon *icons[PUI_STATE_LAST]; PuiState state; gchar *update_command; gchar *error_message; }; G_DEFINE_TYPE(PuiApplication, pui_application, G_TYPE_APPLICATION) enum { PROP_0, PROP_UPDATE_COMMAND, PROP_LAST }; extern gboolean restart; static GParamSpec *properties[PROP_LAST] = { NULL }; static gchar *icon_names[PUI_STATE_LAST][2] = { [PUI_STATE_INITIAL] = { "system-software-update", "update-none" }, [PUI_STATE_UP_TO_DATE] = { "system-software-update", "update-none" }, [PUI_STATE_NORMAL_UPDATES_AVAILABLE] = { "software-update-available", "update-medium" }, [PUI_STATE_IMPORTANT_UPDATES_AVAILABLE] = { "software-update-urgent", "update-high" }, [PUI_STATE_SESSION_RESTART_REQUIRED] = { "system-log-out", "system-log-out" }, [PUI_STATE_SYSTEM_RESTART_REQUIRED] = { "system-reboot", "system-reboot" }, [PUI_STATE_ERROR] = { "dialog-warning", "dialog-warning" } }; static const GOptionEntry cmd_options[] = { { "debug", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, N_("Enable debugging messages"), NULL }, { "quit", 'q', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, N_("Quit running instance of Package Update Indicator"), NULL }, { "version", 'V', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, N_("Print the version number and quit"), NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, NULL, NULL, NULL }, { NULL } }; static void pui_application_show_about_dialog(GSimpleAction *, GVariant *, gpointer); static void pui_application_open_preferences(GSimpleAction *, GVariant *, gpointer); static void pui_application_quit(GSimpleAction *, GVariant *, gpointer); static void pui_application_install_updates(GSimpleAction *, GVariant *, gpointer); static const GActionEntry pui_application_actions[] = { { "about", pui_application_show_about_dialog }, { "preferences", pui_application_open_preferences }, { "quit", pui_application_quit }, { "install-updates", pui_application_install_updates } }; static gboolean program_exists(const gchar *command_line) { gboolean is_program_in_path; gchar **argv = NULL; gchar *program_path; if (!g_shell_parse_argv(command_line, NULL, &argv, NULL)) { return (FALSE); } program_path = g_find_program_in_path(argv[0]); is_program_in_path = (program_path != NULL) ? TRUE : FALSE; g_free(program_path); g_strfreev(argv); return (is_program_in_path); } static void pui_application_show_about_dialog(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { PuiApplication *self = user_data; GtkBuilder *builder; if (self->about_dialog == NULL) { /* get dialog from builder */ builder = gtk_builder_new_from_resource("/org" "/guido-berhoerster/code/package-update-indicator" "/pui-about-dialog.ui"); self->about_dialog = GTK_WIDGET(gtk_builder_get_object(builder, "about-dialog")); g_object_unref(builder); } gtk_dialog_run(GTK_DIALOG(self->about_dialog)); gtk_widget_hide(self->about_dialog); } static void pui_application_open_preferences(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { GDesktopAppInfo *prefs_app_info; GError *error = NULL; prefs_app_info = g_desktop_app_info_new("org.guido-berhoerster.code." "package-update-indicator.preferences.desktop"); if (prefs_app_info == NULL) { g_warning("desktop file \"org.guido-berhoerster.code." "package-update-indicator.preferences.desktop\" not found"); return; } if (!g_app_info_launch(G_APP_INFO(prefs_app_info), NULL, NULL, &error)) { g_warning("failed to launch preferences: %s", error->message); g_error_free(error); } } static void pui_application_quit(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { PuiApplication *self = user_data; /* quit the GTK main loop if the about dialog is running */ if (self->about_dialog != NULL) { gtk_widget_hide(self->about_dialog); } g_application_quit(G_APPLICATION(self)); } static void pui_application_install_updates(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { PuiApplication *self = user_data; GError *error = NULL; if (!g_spawn_command_line_async(self->update_command, &error)) { g_warning("failed to run update command: %s", error->message); g_error_free(error); } } static void update_ui(PuiApplication *self) { GSimpleAction *install_updates_action; guint important_updates = 0; guint normal_updates = 0; gchar *title = NULL; gchar *body = NULL; GtkIconTheme *icon_theme; const gchar * const *icon_namep; const gchar *icon_name; GApplication *application = G_APPLICATION(self); GNotification *notification = NULL; install_updates_action = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(self), "install-updates")); if ((self->state == PUI_STATE_NORMAL_UPDATES_AVAILABLE) || (self->state == PUI_STATE_IMPORTANT_UPDATES_AVAILABLE)) { g_object_get(self->backend, "important-updates", &important_updates, "normal-updates", &normal_updates, NULL); } /* actions */ switch (self->state) { case PUI_STATE_INITIAL: /* FALLTHGROUGH */ case PUI_STATE_UP_TO_DATE: /* FALLTHGROUGH */ case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ case PUI_STATE_SYSTEM_RESTART_REQUIRED: /* FALLTHGROUGH */ case PUI_STATE_ERROR: g_simple_action_set_enabled(install_updates_action, FALSE); break; case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHROUGH */ case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: g_simple_action_set_enabled(install_updates_action, program_exists(self->update_command)); break; } /* title and body for indicator and notification */ switch (self->state) { case PUI_STATE_INITIAL: title = g_strdup(""); body = g_strdup(""); break; case PUI_STATE_UP_TO_DATE: title = g_strdup(_("Up to Date")); body = g_strdup(_("The system is up to date.")); break; case PUI_STATE_NORMAL_UPDATES_AVAILABLE: title = g_strdup(g_dngettext(NULL, "Software Update", "Software Updates", (gulong)normal_updates)); if (normal_updates == 1) { body = g_strdup(_("There is a software update " "available.")); } else { body = g_strdup_printf(_("There are %u " "software updates available."), normal_updates); } break; case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: title = g_strdup(g_dngettext(NULL, "Important Software Update", "Important Software Updates", (gulong)important_updates)); if ((normal_updates == 0) && (important_updates == 1)) { body = g_strdup(_("There is an important " "software update available.")); } else if ((normal_updates == 0) && (important_updates > 1)) { body = g_strdup_printf(_("There are %u " "important software updates available."), important_updates); } else if ((normal_updates > 0) && (important_updates == 1)) { body = g_strdup_printf(_("There are %u " "software updates available, " "one of them is important."), normal_updates + important_updates); } else { body = g_strdup_printf(_("There are %u " "software updates available, " "%u of them are important."), normal_updates + important_updates, important_updates); } break; case PUI_STATE_SESSION_RESTART_REQUIRED: title = g_strdup(_("Logout Required")); body = g_strdup(_("You need to log out and back in for the " "update to take effect.")); break; case PUI_STATE_SYSTEM_RESTART_REQUIRED: title = g_strdup(_("Restart Required")); body = g_strdup(_("The computer has to be restarted for the " "updates to take effect.")); break; case PUI_STATE_ERROR: title = g_strdup(self->error_message); break; } /* indicator */ switch (self->state) { case PUI_STATE_INITIAL: app_indicator_set_status(self->indicator, APP_INDICATOR_STATUS_PASSIVE); break; case PUI_STATE_UP_TO_DATE: /* FALLTHGROUGH */ case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHGROUGH */ case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: /* FALLTHGROUGH */ case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ case PUI_STATE_SYSTEM_RESTART_REQUIRED: /* FALLTHGROUGH */ case PUI_STATE_ERROR: app_indicator_set_status(self->indicator, APP_INDICATOR_STATUS_ACTIVE); break; } /* determine icon name using fallbacks if necessary */ icon_theme = gtk_icon_theme_get_default(); for (icon_namep = g_themed_icon_get_names(G_THEMED_ICON(self->icons[self->state])), icon_name = *icon_namep; *icon_namep != NULL; icon_namep++) { if (gtk_icon_theme_has_icon(icon_theme, *icon_namep)) { icon_name = *icon_namep; break; } } app_indicator_set_icon_full(self->indicator, icon_name, title); /* notification */ switch (self->state) { case PUI_STATE_INITIAL: /* FALLTHGROUGH */ case PUI_STATE_UP_TO_DATE: /* FALLTHGROUGH */ case PUI_STATE_ERROR: /* withdraw exisiting notification */ g_application_withdraw_notification(application, "package-updates-or-restart-required"); break; case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHGROUGH */ case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: /* FALLTHGROUGH */ case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ case PUI_STATE_SYSTEM_RESTART_REQUIRED: /* create notification */ notification = g_notification_new(title); g_notification_set_body(notification, body); g_notification_set_icon(notification, self->icons[self->state]); g_notification_set_priority(notification, G_NOTIFICATION_PRIORITY_NORMAL); if (g_action_get_enabled(G_ACTION(install_updates_action))) { g_notification_add_button(notification, _("Install Updates"), "app.install-updates"); } g_application_send_notification(application, "package-updates-or-restart-required", notification); break; } if (notification != NULL) { g_object_unref(notification); } g_debug("indicator icon: %s, notification title: \"%s\", " "notification body: \"%s\"", icon_name, title, body); g_free(body); g_free(title); } static void transition_state(PuiApplication *self) { PuiState state = self->state; PuiRestart restart_type; guint important_updates; guint normal_updates; gchar *old_state; gchar *new_state; switch (self->state) { case PUI_STATE_INITIAL: /* FALLTHROUGH */ case PUI_STATE_UP_TO_DATE: /* FALLTHROUGH */ case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHROUGH */ case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: if (self->error_message != NULL) { state = PUI_STATE_ERROR; break; } g_object_get(self->backend, "restart-type", &restart_type, "important-updates", &important_updates, "normal-updates", &normal_updates, NULL); if (restart_type == PUI_RESTART_SESSION) { state = PUI_STATE_SESSION_RESTART_REQUIRED; } else if (restart_type == PUI_RESTART_SYSTEM) { state = PUI_STATE_SYSTEM_RESTART_REQUIRED; } else if (important_updates > 0) { state = PUI_STATE_IMPORTANT_UPDATES_AVAILABLE; } else if (normal_updates > 0) { state = PUI_STATE_NORMAL_UPDATES_AVAILABLE; } else { state = PUI_STATE_UP_TO_DATE; } break; case PUI_STATE_SESSION_RESTART_REQUIRED: g_object_get(self->backend, "restart-type", &restart_type, NULL); if (restart_type == PUI_RESTART_SYSTEM) { state = PUI_STATE_SYSTEM_RESTART_REQUIRED; } break; case PUI_STATE_SYSTEM_RESTART_REQUIRED: /* FALLTHROUGH */ case PUI_STATE_ERROR: break; } if (state != self->state) { old_state = pui_types_enum_to_string(PUI_TYPE_STATE, self->state); new_state = pui_types_enum_to_string(PUI_TYPE_STATE, state); g_debug("state %s -> %s", old_state, new_state); self->state = state; update_ui(self); g_free(new_state); g_free(old_state); } } static void on_backend_restart_required(PuiBackend *backend, gpointer user_data) { PuiApplication *self = user_data; restart = TRUE; g_action_group_activate_action(G_ACTION_GROUP(G_APPLICATION(self)), "quit", NULL); } static void on_backend_state_changed(PuiBackend *backend, gpointer user_data) { PuiApplication *self = user_data; transition_state(self); } static void on_pui_backend_finished(GObject *source_object, GAsyncResult *result, gpointer user_data) { PuiApplication *self = user_data; GError *error = NULL; self->backend = pui_backend_new_finish(result, &error); if (self->backend == NULL) { g_warning("failed to instantiate backend: %s", error->message); g_free(self->error_message); g_error_free(error); self->error_message = g_strdup(_("Update notifications " "are not supported.")); transition_state(self); return; } pui_backend_set_proxy(self->backend, g_getenv("http_proxy"), g_getenv("https_proxy"), g_getenv("ftp_proxy"), g_getenv("socks_proxy"), g_getenv("no_proxy"), NULL); g_settings_bind(self->settings, "refresh-interval", self->backend, "refresh-interval", G_SETTINGS_BIND_GET); g_settings_bind(self->settings, "use-mobile-connection", self->backend, "use-mobile-connection", G_SETTINGS_BIND_GET); transition_state(self); g_signal_connect(self->backend, "restart-required", G_CALLBACK(on_backend_restart_required), self); g_signal_connect(self->backend, "state-changed", G_CALLBACK(on_backend_state_changed), self); } static void pui_application_startup(GApplication *application) { PuiApplication *self = PUI_APPLICATION(application); gsize i; GtkBuilder *builder; GtkWidget *menu; G_APPLICATION_CLASS(pui_application_parent_class)->startup(application); /* create actions */ g_action_map_add_action_entries(G_ACTION_MAP(self), pui_application_actions, G_N_ELEMENTS(pui_application_actions), self); /* load icons */ for (i = 0; i < G_N_ELEMENTS(self->icons); i++) { self->icons[i] = g_themed_icon_new_from_names(icon_names[i], 2); } /* create settings */ self->settings = pui_settings_new(); g_settings_bind(self->settings, "update-command", self, "update-command", G_SETTINGS_BIND_GET); /* start instantiating backend */ pui_backend_new_async(self->cancellable, on_pui_backend_finished, self); /* create indicator */ self->indicator = app_indicator_new(APPLICATION_ID, "system-software-update", APP_INDICATOR_CATEGORY_APPLICATION_STATUS); app_indicator_set_title(self->indicator, _("Package Update Indicator")); /* get menu from builder and add it to the indicator */ builder = gtk_builder_new_from_resource("/org/guido-berhoerster/code/" "package-update-indicator/pui-menu.ui"); menu = GTK_WIDGET(gtk_builder_get_object(builder, "menu")); gtk_widget_insert_action_group(menu, "app", G_ACTION_GROUP(self)); gtk_widget_show_all(menu); app_indicator_set_menu(self->indicator, GTK_MENU(menu)); update_ui(self); /* keep GApplication running */ g_application_hold(application); g_object_unref(builder); } static void pui_application_shutdown(GApplication *application) { GApplicationClass *application_class = G_APPLICATION_CLASS(pui_application_parent_class); application_class->shutdown(application); } static gint pui_application_handle_local_options(GApplication *application, GVariantDict *options) { gchar *messages_debug; gchar **args = NULL; GError *error = NULL; /* filename arguments are not allowed */ if (g_variant_dict_lookup(options, G_OPTION_REMAINING, "^a&ay", &args)) { g_printerr("invalid argument: \"%s\"\n", args[0]); g_free(args); return (1); } if (g_variant_dict_contains(options, "version")) { g_print("%s %s\n", PACKAGE, VERSION); /* quit */ return (0); } if (g_variant_dict_contains(options, "debug")) { /* enable debug logging */ messages_debug = g_strjoin(":", G_LOG_DOMAIN, g_getenv("G_MESSAGES_DEBUG"), NULL); g_setenv("G_MESSAGES_DEBUG", messages_debug, TRUE); g_free(messages_debug); } /* * register with the session bus so that it is possible to discern * between remote and primary instance and that remote actions can be * invoked, this causes the startup signal to be emitted which, in case * of the primary instance, starts to instantiate the * backend with the given values */ if (!g_application_register(application, NULL, &error)) { g_critical("g_application_register: %s", error->message); g_error_free(error); return (1); } if (g_variant_dict_contains(options, "quit")) { /* only valid if a remote instance is running */ if (!g_application_get_is_remote(application)) { g_printerr("%s is not running\n", g_get_prgname()); return (1); } /* signal remote instance to quit */ g_action_group_activate_action(G_ACTION_GROUP(application), "quit", NULL); /* quit local instance */ return (0); } /* proceed with default command line processing */ return (-1); } static void pui_application_activate(GApplication *application) { GApplicationClass *application_class = G_APPLICATION_CLASS(pui_application_parent_class); /* do nothing, implementation required by GApplication */ application_class->activate(application); } static void pui_application_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PuiApplication *self = PUI_APPLICATION(object); switch (property_id) { case PROP_UPDATE_COMMAND: g_free(self->update_command); self->update_command = g_value_dup_string(value); g_debug("property \"update-command\" set to \"%s\"", self->update_command); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void pui_application_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PuiApplication *self = PUI_APPLICATION(object); switch (property_id) { case PROP_UPDATE_COMMAND: g_value_set_string(value, self->update_command); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void pui_application_dispose(GObject *object) { PuiApplication *self = PUI_APPLICATION(object); gsize i; if (self->settings != NULL) { g_signal_handlers_disconnect_by_data(self->settings, self); g_clear_object(&self->settings); } if (self->cancellable != NULL) { g_cancellable_cancel(self->cancellable); g_clear_object(&self->cancellable); } if (self->backend != NULL) { g_clear_object(&self->backend); } if (self->indicator != NULL) { g_clear_object(&self->indicator); } if (self->about_dialog != NULL) { g_clear_pointer(&self->about_dialog, (GDestroyNotify)(gtk_widget_destroy)); } for (i = 0; i < G_N_ELEMENTS(self->icons); i++) { if (self->icons[i] != NULL) { g_clear_object(&self->icons[i]); } } G_OBJECT_CLASS(pui_application_parent_class)->dispose(object); } static void pui_application_finalize(GObject *object) { PuiApplication *self = PUI_APPLICATION(object); g_free(self->update_command); g_free(self->error_message); G_OBJECT_CLASS(pui_application_parent_class)->finalize(object); } static void pui_application_class_init(PuiApplicationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GApplicationClass *application_class = G_APPLICATION_CLASS(klass); object_class->set_property = pui_application_set_property; object_class->get_property = pui_application_get_property; object_class->dispose = pui_application_dispose; object_class->finalize = pui_application_finalize; properties[PROP_UPDATE_COMMAND] = g_param_spec_string("update-command", "Update command", "Command for installing updates", NULL, G_PARAM_READWRITE); g_object_class_install_properties(object_class, PROP_LAST, properties); application_class->startup = pui_application_startup; application_class->shutdown = pui_application_shutdown; application_class->handle_local_options = pui_application_handle_local_options; application_class->activate = pui_application_activate; } static void pui_application_init(PuiApplication *self) { g_application_add_main_option_entries(G_APPLICATION(self), cmd_options); self->cancellable = g_cancellable_new(); } PuiApplication * pui_application_new(void) { return (g_object_new(PUI_TYPE_APPLICATION, "application-id", APPLICATION_ID, NULL)); } package-update-indicator-5/org.guido-berhoerster.code.package-update-indicator.desktop.in010064400017500001750000000004171353220474000305040ustar00gbergber[Desktop Entry] Name=Package Update Indicator GenericName=Package Update Indicator Comment=Notify about available software updates Icon=system-software-update Exec=package-update-indicator Terminal=false Type=Application Categories=Utility;GTK;TrayIcon; NotShowIn=GNOME; package-update-indicator-5/package-update-indicator.1.xml010064400017500001750000000130531353220474000222360ustar00gbergber Guido Berhoerster guido+pui@berhoerster.name 19 June, 2018 package-update-indicator 1 User Commands package-update-indicator notify about available software updates package-update-indicator Description The package-update-indicator utility regularly checks for software updates and notifies the user about available updates using desktop notifications and either a status notifier icon or a system tray icon. Protocol-specific proxies specified through the corresponding environment variables will be used by PackagKit when refreshing metadata if the user is allowed to use the polkit action org.freedesktop.packagekit.system-network-proxy-configure without authentication. Options The following options are supported: Quit the running instance of package-update-indicator. Print the version number and exit. Environment Variables http_proxy Network proxy using the HTTP protcol. https_proxy Network proxy using the HTTPS protcol. ftp_proxy Network proxy using the FTP protcol. socks_proxy Network proxy using the SOCKS protcol. no_proxy Comma-separated list of host for which no proxy should be used. Exit Status The following exit values are returned: 0 Command successfully executed. 1 An unspecified error has occured. 2 Invalid command line options were specified. See Also package-update-indicator-prefs 1, polkit 8 package-update-indicator-5/pui-menu.ui010064400017500001750000000025631353220474000166320ustar00gbergber True False True False app.install-updates _Install updates True True False app.preferences _Preferences… True True False app.about _About… True package-update-indicator-5/pui-application.h010064400017500001750000000033751353220474000200050ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PUI_APPLICATION_H #define PUI_APPLICATION_H #include #include G_BEGIN_DECLS #define PUI_TYPE_APPLICATION (pui_application_get_type()) G_DECLARE_FINAL_TYPE(PuiApplication, pui_application, PUI, APPLICATION, GApplication) typedef enum { PUI_STATE_INITIAL, PUI_STATE_UP_TO_DATE, PUI_STATE_NORMAL_UPDATES_AVAILABLE, PUI_STATE_IMPORTANT_UPDATES_AVAILABLE, PUI_STATE_SESSION_RESTART_REQUIRED, PUI_STATE_SYSTEM_RESTART_REQUIRED, PUI_STATE_ERROR, PUI_STATE_LAST } PuiState; PuiApplication * pui_application_new(void); G_END_DECLS #endif /* !PUI_APPLICATION_H */ package-update-indicator-5/org.guido-berhoerster.code.package-update-indicator.gschema.xml010064400017500001750000000015451353220474000306370ustar00gbergber "" Update command Command for installing updates. 86400 Refresh interval The interval in seconds for refreshing metadata. false Whether to use a mobile connection If enabled, use a mobile connection refreshing the package cache. package-update-indicator-5/pui-get-updates.c010064400017500001750000000152441353220474000177150ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "pui-get-updates.h" typedef struct { PkControl *pk_control; PkTask *pk_task; guint refresh_interval; } PuiGetUpdates; GQuark pui_get_updates_error_quark(void) { return (g_quark_from_static_string("pui-get-updates-error-quark")); } static void on_get_updates_finished(GObject *source_object, GAsyncResult *async_result, gpointer user_data) { GTask *task = user_data; PuiGetUpdates *get_updates; PkResults *results = NULL; PkError *pk_error = NULL; GError *error = NULL; gint error_code; GPtrArray *package_list; get_updates = g_task_get_task_data(task); g_debug("get updates transaction finished"); results = pk_client_generic_finish(PK_CLIENT(get_updates->pk_task), async_result, &error); if (results == NULL) { /* pass the error on */ g_task_return_error(task, error); goto out; } pk_error = pk_results_get_error_code(results); if (pk_error != NULL) { /* transaction failed, return error */ g_debug("failed to refresh the cache: %s", pk_error_get_details(pk_error)); if (pk_error_get_code(pk_error) == PK_ERROR_ENUM_TRANSACTION_CANCELLED) { error_code = PUI_GET_UPDATES_ERROR_CANCELLED; } else { error_code = PUI_GET_UPDATES_ERROR_GET_UPDATES_FAILED; } error = g_error_new(PUI_GET_UPDATES_ERROR, error_code, "Failed to get package updates: %s", pk_error_get_details(pk_error)); g_task_return_error(task, error); g_object_unref(pk_error); goto out; } /* return results */ package_list = pk_results_get_package_array(results); g_assert(package_list != NULL); g_task_return_pointer(task, package_list, (GDestroyNotify)g_ptr_array_unref); out: if (results != NULL) { g_object_unref(results); } g_object_unref(task); } static void on_refresh_cache_finished(GObject *source_object, GAsyncResult *async_result, gpointer user_data) { GTask *task = user_data; PuiGetUpdates *get_updates; PkResults *results = NULL; PkClient *pk_client; GError *error = NULL; PkError *pk_error = NULL; gint error_code; get_updates = g_task_get_task_data(task); pk_client = PK_CLIENT(get_updates->pk_task); g_debug("refresh cache transaction finished"); results = pk_client_generic_finish(pk_client, async_result, &error); if (results == NULL) { g_task_return_error(task, error); goto out; } pk_error = pk_results_get_error_code(results); if (pk_error != NULL) { /* transaction failed, return error */ g_debug("failed to refresh the cache: %s", pk_error_get_details(pk_error)); if (pk_error_get_code(pk_error) == PK_ERROR_ENUM_TRANSACTION_CANCELLED) { error_code = PUI_GET_UPDATES_ERROR_CANCELLED; } else { error_code = PUI_GET_UPDATES_ERROR_REFRESH_FAILED; } error = g_error_new(PUI_GET_UPDATES_ERROR, error_code, "Failed to refresh the cache: %s", pk_error_get_details(pk_error)); g_task_return_error(task, error); g_object_unref(pk_error); goto out; } /* cache is up to date, get updates */ pk_client_get_updates_async(pk_client, pk_bitfield_value(PK_FILTER_ENUM_NONE), g_task_get_cancellable(task), NULL, NULL, on_get_updates_finished, task); out: if (results != NULL) { g_object_unref(results); } } static void on_get_time_since_refresh_finished(GObject *source_object, GAsyncResult *async_result, gpointer user_data) { GTask *task = user_data; PuiGetUpdates *get_updates; guint last_refresh; GError *error = NULL; PkClient *pk_client; get_updates = g_task_get_task_data(task); pk_client = PK_CLIENT(get_updates->pk_task); last_refresh = pk_control_get_time_since_action_finish(get_updates->pk_control, async_result, &error); if (last_refresh == 0) { g_task_return_error(task, error); g_object_unref(task); return; } g_debug("time since last cache refresh: %us", last_refresh); if (last_refresh > get_updates->refresh_interval) { /* cache is out of date, refresh first */ g_debug("refreshing the cache"); pk_client_refresh_cache_async(pk_client, FALSE, g_task_get_cancellable(task), NULL, NULL, on_refresh_cache_finished, task); } else { /* cache is up to date, get updates */ g_debug("getting updates"); pk_client_get_updates_async(pk_client, pk_bitfield_value(PK_FILTER_ENUM_NONE), g_task_get_cancellable(task), NULL, NULL, on_get_updates_finished, task); } } static void pui_get_updates_free(gpointer data) { PuiGetUpdates *get_updates = data; g_object_unref(get_updates->pk_control); g_object_unref(get_updates->pk_task); g_slice_free(PuiGetUpdates, data); } void pui_get_updates_async(PkControl *pk_control, guint refresh_interval, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { PuiGetUpdates *get_updates; GTask *task; PkClient *pk_client; get_updates = g_slice_new0(PuiGetUpdates); get_updates->pk_control = g_object_ref(pk_control); get_updates->pk_task = pk_task_new(); get_updates->refresh_interval = refresh_interval; pk_client = PK_CLIENT(get_updates->pk_task); pk_client_set_cache_age(pk_client, refresh_interval); pk_client_set_background(pk_client, TRUE); task = g_task_new(NULL, cancellable, callback, user_data); g_task_set_task_data(task, get_updates, pui_get_updates_free); /* check whether to refresh the cache before checking for updates */ g_debug("getting the time since the cache was last refreshed"); pk_control_get_time_since_action_async(pk_control, PK_ROLE_ENUM_REFRESH_CACHE, cancellable, on_get_time_since_refresh_finished, task); } GPtrArray * pui_get_updates_finish(GAsyncResult *result, GError **errorp) { return (g_task_propagate_pointer(G_TASK(result), errorp)); } package-update-indicator-5/pui-prefs-application.c010064400017500001750000000155201353220474000211100ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include "pui-prefs-application.h" #include "pui-settings.h" #define COLUMN_REFRESH_INTERVAL 2 struct _PuiPrefsApplication { GtkApplication parent_instance; GSettings *settings; }; G_DEFINE_TYPE(PuiPrefsApplication, pui_prefs_application, GTK_TYPE_APPLICATION) static void pui_prefs_application_quit(GSimpleAction *, GVariant *, gpointer); static const GActionEntry pui_prefs_application_actions[] = { { "quit", pui_prefs_application_quit } }; static void pui_prefs_application_quit(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { PuiPrefsApplication *self = user_data; g_application_quit(G_APPLICATION(self)); } static gboolean map_refresh_interval_to_index(GValue *value, GVariant *variant, gpointer user_data) { GtkTreeModel *tree_model = user_data; guint32 setting_interval; gint index; gboolean iter_continue; GtkTreeIter iter = { 0 }; GValue model_value = G_VALUE_INIT; guint model_interval; setting_interval = g_variant_get_uint32(variant); /* try to find a matching entry in the list */ for (iter_continue = gtk_tree_model_get_iter_first(tree_model, &iter), index = 0; iter_continue; iter_continue = gtk_tree_model_iter_next(tree_model, &iter), index++) { gtk_tree_model_get_value(tree_model, &iter, COLUMN_REFRESH_INTERVAL, &model_value); model_interval = g_value_get_uint(&model_value); g_value_unset(&model_value); if (setting_interval == model_interval) { g_debug("mapping refresh-interval %" G_GUINT32_FORMAT " to index %d", setting_interval, index); g_value_set_int(value, index); return (TRUE); } } g_debug("mapping refresh-interval %" G_GUINT32_FORMAT " to index -1", setting_interval); g_value_set_int(value, -1); return (TRUE); } static GVariant * map_index_to_refresh_interval(const GValue *value, const GVariantType *expected_type, gpointer user_data) { GtkTreeModel *tree_model = GTK_TREE_MODEL(user_data); gint index; GtkTreeIter iter = { 0 }; GValue model_value = G_VALUE_INIT; guint model_interval; index = g_value_get_int(value); if (!gtk_tree_model_iter_nth_child(tree_model, &iter, NULL, index)) { return (NULL); } gtk_tree_model_get_value(tree_model, &iter, COLUMN_REFRESH_INTERVAL, &model_value); model_interval = g_value_get_uint(&model_value); g_debug("mapping index %d to refresh-interval value %" G_GUINT32_FORMAT, index, model_interval); g_value_unset(&model_value); return (g_variant_new_uint32(model_interval)); } static void pui_prefs_application_startup(GApplication *application) { PuiPrefsApplication *self = PUI_PREFS_APPLICATION(application); GApplicationClass *application_class = G_APPLICATION_CLASS(pui_prefs_application_parent_class); GtkBuilder *builder; GtkWidget *window; GtkTreeModel *tree_model; GtkWidget *update_command_entry; GtkWidget *refresh_interval_combo_box; GtkWidget *use_mobile_check_button; application_class->startup(application); /* create actions */ g_action_map_add_action_entries(G_ACTION_MAP(self), pui_prefs_application_actions, G_N_ELEMENTS(pui_prefs_application_actions), self); /* get widgets from builder */ builder = gtk_builder_new_from_resource("/org/guido-berhoerster/code/" "package-update-indicator/preferences/pui-prefs-window.ui"); window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); gtk_application_add_window(GTK_APPLICATION(self), GTK_WINDOW(window)); update_command_entry = GTK_WIDGET(gtk_builder_get_object(builder, "update-command")); refresh_interval_combo_box = GTK_WIDGET(gtk_builder_get_object(builder, "refresh-interval")); tree_model = gtk_combo_box_get_model(GTK_COMBO_BOX(refresh_interval_combo_box)); use_mobile_check_button = GTK_WIDGET(gtk_builder_get_object(builder, "use-mobile-connection")); /* bind settings to widgets */ self->settings = pui_settings_new(); g_settings_bind(self->settings, "update-command", update_command_entry, "text", G_SETTINGS_BIND_DEFAULT); g_settings_bind_with_mapping(self->settings, "refresh-interval", refresh_interval_combo_box, "active", G_SETTINGS_BIND_DEFAULT, map_refresh_interval_to_index, map_index_to_refresh_interval, tree_model, NULL); g_settings_bind(self->settings, "use-mobile-connection", use_mobile_check_button, "active", G_SETTINGS_BIND_DEFAULT); /* show window */ gtk_widget_show(window); gtk_window_present(GTK_WINDOW(window)); g_object_unref(builder); } static void pui_prefs_application_activate(GApplication *application) { GtkApplication *gtk_application = GTK_APPLICATION(application); GApplicationClass *application_class = G_APPLICATION_CLASS(pui_prefs_application_parent_class); /* raise window when activated */ gtk_window_present(gtk_application_get_active_window(gtk_application)); application_class->activate(application); } static void pui_prefs_application_dispose(GObject *object) { PuiPrefsApplication *self = PUI_PREFS_APPLICATION(object); if (self->settings != NULL) { g_clear_object(&self->settings); } G_OBJECT_CLASS(pui_prefs_application_parent_class)->dispose(object); } static void pui_prefs_application_class_init(PuiPrefsApplicationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GApplicationClass *application_class = G_APPLICATION_CLASS(klass); object_class->dispose = pui_prefs_application_dispose; application_class->startup = pui_prefs_application_startup; application_class->activate = pui_prefs_application_activate; } static void pui_prefs_application_init(PuiPrefsApplication *self) { /* do nothing, implementation required */ } PuiPrefsApplication * pui_prefs_application_new(void) { return (g_object_new(PUI_TYPE_PREFS_APPLICATION, "application-id", APPLICATION_ID, NULL)); } package-update-indicator-5/docbook-update-source-data.xsl010064400017500001750000000015111353220474000223610ustar00gbergber package-update-indicator-5/pui-types.c.in010064400017500001750000000024471353220474000172450ustar00gbergber/*** BEGIN file-header ***/ #include "pui-types.h" /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ #include "@filename@" /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) { static volatile gsize g_define_type_id__volatile; GType g_@type@_type_id; if (g_once_init_enter(&g_define_type_id__volatile)) { static const G@Type@Value values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0 } }; g_@type@_type_id = g_@type@_register_static( g_intern_static_string("@EnumName@"), values); g_once_init_leave(&g_define_type_id__volatile, g_@type@_type_id); } return (g_define_type_id__volatile); } /*** END value-tail ***/ /*** BEGIN file-tail ***/ gchar * pui_types_enum_to_string(GType type, gint value) { GTypeClass *type_class; GEnumValue *enum_value; type_class = g_type_class_ref(type); g_return_val_if_fail(G_IS_ENUM_CLASS(type_class), NULL); enum_value = g_enum_get_value(G_ENUM_CLASS(type_class), value); if (enum_value == NULL) { return (g_strdup_printf("%d", value)); } return (g_strdup(enum_value->value_nick)); } /*** END file-tail ***/ package-update-indicator-5/pui-prefs-application.h010064400017500001750000000030431353220474000211120ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PUI_PREFS_APPLICATION_H #define PUI_PREFS_APPLICATION_H #include #include G_BEGIN_DECLS #define PUI_TYPE_PREFS_APPLICATION (pui_prefs_application_get_type()) G_DECLARE_FINAL_TYPE(PuiPrefsApplication, pui_prefs_application, PUI, PREFS_APPLICATION, GtkApplication) PuiPrefsApplication * pui_prefs_application_new(void); G_END_DECLS #endif /* !PUI_PREFS_APPLICATION_H */ package-update-indicator-5/Makefile010064400017500001750000000220651353220474000161730ustar00gbergber# # Copyright (C) 2018 Guido Berhoerster # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # PACKAGE = package-update-indicator APPLICATION_ID = org.guido-berhoerster.code.package-update-indicator PREFS_APPLICATION_ID = org.guido-berhoerster.code.package-update-indicator.preferences VERSION = 5 DISTNAME = $(PACKAGE)-$(VERSION) AUTHOR = Guido Berhoerster BUG_ADDRESS = guido+pui@berhoerster.name # gcc, clang, icc, Sun/Solaris Studio CC := $(CC) -std=c99 COMPILE.c = $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(XCPPFLAGS) $(TARGET_ARCH) -c # gcc, clang, icc MAKEDEPEND.c = $(CC) -MM $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(XCPPFLAGS) # Sun/Solaris Studio #MAKEDEPEND.c = $(CC) -xM1 $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(XCPPFLAGS) # X makedepend #MAKEDEPEND.c = makedepend -f- -Y -- $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(XCPPFLAGS) -- LINK.c = $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(XCPPFLAGS) $(LDFLAGS) $(XLDFLAGS) $(TARGET_ARCH) LINK.o = $(CC) $(LDFLAGS) $(XLDFLAGS) $(TARGET_ARCH) CP := cp INSTALL := install INSTALL.exec := $(INSTALL) -D -m 0755 INSTALL.data := $(INSTALL) -D -m 0644 INSTALL.link := $(CP) -f -P PAX := pax GZIP := gzip SED := sed GLIB_COMPILE_SCHEMAS := $(shell pkg-config --variable=glib_compile_schemas gio-2.0) GLIB_COMPILE_RESOURCES := $(shell pkg-config --variable=glib_compile_resources gio-2.0) GLIB_MKENUMS := $(shell pkg-config --variable=glib_mkenums glib-2.0) XSLTPROC := xsltproc DOCBOOK5_MANPAGES_STYLESHEET = http://docbook.sourceforge.net/release/xsl-ns/current/manpages/docbook.xsl DOCBOOK5_MANPAGES_FLAGS = --stringparam man.authors.section.enabled 0 \ --stringparam man.copyright.section.enabled 0 MSGFMT = msgfmt MSGMERGE = msgmerge XGETTEXT = xgettext XGETTEXT_OPTIONS = --copyright-holder "$(AUTHOR)" \ --package-name '$(PACKAGE)' \ --package-version '$(VERSION)' \ --msgid-bugs-address '$(BUG_ADDRESS)' \ --default-domain '$(PACKAGE)' \ --from-code UTF-8 \ --keyword=_ \ --keyword=N_ \ --keyword=C_:1c,2 \ --keyword=NC_:1c,2 \ --keyword=g_dngettext:2,3 \ --add-comments INDICATOR_LIB := $(or \ $(shell pkg-config --exists appindicator3-0.1 && \ printf '%s\\\n' appindicator3-0.1), \ $(shell pkg-config --exists ayatana-appindicator3-0.1 && \ printf '%s\\\n' ayatana-appindicator3-0.1), \ appindicator3-0.1) INDICATOR_FLAG := $(if $(findstring ayatana,$(INDICATOR_LIB)), \ -DHAVE_AYATANA_APPINDICATOR,) define generate-manpage-rule = %.$1: %.$(addsuffix .xml,$1) docbook-update-source-data.xsl $$(XSLTPROC) \ --xinclude \ --stringparam package $$(PACKAGE) \ --stringparam version $$(VERSION) \ docbook-update-source-data.xsl $$< | \ $$(XSLTPROC) \ --xinclude \ --output $$@ \ $$(DOCBOOK5_MANPAGES_FLAGS) \ $$(DOCBOOK5_MANPAGES_STYLESHEET) \ - endef DESTDIR ?= prefix ?= /usr/local bindir ?= $(prefix)/bin datadir ?= $(prefix)/share mandir ?= $(datadir)/man localedir ?= $(datadir)/locale sysconfdir ?= /etc xdgautostartdir ?= $(sysconfdir)/xdg/autostart xdgapplicationsdir ?= $(datadir)/applications OS_NAME := $(shell uname -s) OS_RELEASE := $(shell uname -r) $(PACKAGE)_OBJS = package-update-indicator.o \ pui-application.o \ pui-backend.o \ pui-get-updates.o \ pui-settings.o \ pui-types.o \ pui-resources.o $(PACKAGE)-prefs_OBJS = package-update-indicator-prefs.o \ pui-prefs-application.o \ pui-settings.o \ pui-prefs-resources.o OBJS = $($(PACKAGE)_OBJS) $($(PACKAGE)-prefs_OBJS) ENUM_DEPS = pui-backend.h \ pui-application.h ENUM_HEADER = pui-types.h ENUM_FILES = $(ENUM_HEADER) \ pui-types.c GSETTINGS_SCHEMAS = $(APPLICATION_ID).gschema.xml GRESOURCE_FILES = pui-prefs.gresource.xml AUTOSTART_FILE = $(APPLICATION_ID).desktop DESKTOP_FILES = $(PREFS_APPLICATION_ID).desktop LINGUAS := $(shell sed 's/\#.*//' po/LINGUAS) MOFILES := $(patsubst %,po/%.mo,$(LINGUAS)) POTFILES_IN := $(shell sed 's/\#.*//' po/POTFILES.in) POTFILE = po/$(PACKAGE).pot MANPAGES = $(PACKAGE).1 $(PACKAGE)-prefs.1 .DEFAULT_TARGET = all .PHONY: all pot update-po clean clobber dist install all: $(PACKAGE) $(PACKAGE)-prefs $(AUTOSTART_FILE) $(DESKTOP_FILES) $(MOFILES) $(MANPAGES) $(PACKAGE): XCPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" \ -DAPPLICATION_ID=\"$(APPLICATION_ID)\" \ -DVERSION=\"$(VERSION)\" \ -DG_LOG_DOMAIN=\"$(PACKAGE)\" \ -DPACKAGE_LOCALE_DIR="\"$(localedir)\"" \ -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \ -DSETTINGS_SCHEMA_ID=\"$(APPLICATION_ID)\" \ -DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE \ $(INDICATOR_FLAG) $(PACKAGE): XCFLAGS = $(shell pkg-config --cflags gtk+-3.0 \ $(INDICATOR_LIB) packagekit-glib2 \ polkit-gobject-1 upower-glib) $(PACKAGE): LDLIBS = $(shell pkg-config --libs gtk+-3.0 \ $(INDICATOR_LIB) packagekit-glib2 \ polkit-gobject-1 upower-glib) $(PACKAGE)-prefs: XCPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" \ -DAPPLICATION_ID=\"$(PREFS_APPLICATION_ID)\" \ -DVERSION=\"$(VERSION)\" \ -DG_LOG_DOMAIN=\"$(PACKAGE)\" \ -DPACKAGE_LOCALE_DIR="\"$(localedir)\"" \ -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \ -DSETTINGS_SCHEMA_ID=\"$(APPLICATION_ID)\" $(PACKAGE)-prefs: XCFLAGS = $(shell pkg-config --cflags gtk+-3.0) $(PACKAGE)-prefs: LDLIBS = $(shell pkg-config --libs gtk+-3.0) ifneq ($(findstring $(OS_NAME),FreeBSD DragonFly OpenBSD),) $(PACKAGE): XCPPFLAGS += -I/usr/local/include $(PACKAGE): XLDFLAGS += -L/usr/local/lib else ifeq ($(OS_NAME),NetBSD) $(PACKAGE): XCPPFLAGS += -I/usr/pkg/include $(PACKAGE): XLDFLAGS += -L/usr/pkg/lib endif ifeq ($(findstring $(OS_NAME),FreeBSD DragonFly NetBSD OpenBSD),) $(PACKAGE): XCPPFLAGS += -D_XOPEN_SOURCE=600 endif $(PACKAGE): $($(PACKAGE)_OBJS) $(LINK.o) $^ $(LDLIBS) -o $@ $(PACKAGE)-prefs: $($(PACKAGE)-prefs_OBJS) $(LINK.o) $^ $(LDLIBS) -o $@ $(OBJS): $(ENUM_HEADER) %-types.h: %-types.h.in $(ENUM_DEPS) $(GLIB_MKENUMS) --template $< >$@ $(filter-out $<,$^) %-types.c: %-types.c.in $(ENUM_DEPS) $(GLIB_MKENUMS) --template $< >$@ $(filter-out $<,$^) %-resources.c: %.gresource.xml $(GLIB_COMPILE_RESOURCES) --generate-dependencies $< | \ while read -r resource_file; do \ printf '%s: %s\n' $@ "$${resource_file}"; \ done $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=. --generate-source $< $(POTFILE): po/POTFILES.in $(POTFILES_IN) $(XGETTEXT) $(XGETTEXT_OPTIONS) --files-from $< --output $@ pot: $(POTFILE) update-po: $(POTFILE) for pofile in $(patsubst %.mo,%.po,$(MOFILES)); do \ $(MSGMERGE) --update --backup off $$pofile $<; \ done %.mo: %.po $(MSGFMT) --output $@ $< %.desktop: %.desktop.in $(MSGFMT) --desktop --keyword 'Keywords' --template $< -d po --output $@ $(foreach section,1 2 3 4 5 6 7 8 9,$(eval $(call generate-manpage-rule,$(section)))) %.o: %.c $(MAKEDEPEND.c) $< | $(SED) -f deps.sed >$*.d $(COMPILE.c) -o $@ $< install: all $(INSTALL.exec) $(PACKAGE) "$(DESTDIR)$(bindir)/$(PACKAGE)" $(INSTALL.exec) $(PACKAGE)-prefs \ "$(DESTDIR)$(bindir)/$(PACKAGE)-prefs" for schema in $(GSETTINGS_SCHEMAS); do \ $(INSTALL.data) $${schema} \ $(DESTDIR)$(datadir)/glib-2.0/schemas/$${schema}; \ done if [ -n "$(GSETTINGS_SCHEMAS)" ] && [ -z "$(DESTDIR)" ]; then \ $(GLIB_COMPILE_SCHEMAS) $(datadir)/glib-2.0/schemas; \ fi $(INSTALL.data) $(AUTOSTART_FILE) \ $(DESTDIR)$(xdgautostartdir)/$(AUTOSTART_FILE) for desktop_file in $(DESKTOP_FILES); do \ $(INSTALL.data) $${desktop_file} \ $(DESTDIR)$(xdgapplicationsdir)/$${desktop_file}; \ done for lang in $(LINGUAS); do \ $(INSTALL.data) po/$${lang}.mo \ $(DESTDIR)$(localedir)/$${lang}/LC_MESSAGES/$(PACKAGE).mo; \ done for manpage in $(MANPAGES); do \ $(INSTALL.data) $${manpage} \ "$(DESTDIR)$(mandir)/man$${manpage##*.}/$${manpage##*/}"; \ done clean: rm -f $(PACKAGE) $(OBJS) $(ENUM_FILES) $(AUTOSTART_FILE) \ $(DESKTOP_FILES) $(POTFILE) $(MOFILES) $(MANPAGES) clobber: clean rm -f $(patsubst %.o,%.d,$(OBJS)) dist: clobber $(PAX) -w -x ustar -s ',.*/\..*,,' -s ',./[^/]*\.tar\.gz,,' \ -s ',^\.$$,,' -s ',\./,$(DISTNAME)/,' . | \ $(GZIP) > $(DISTNAME).tar.gz -include local.mk -include $(patsubst %.o,%.d,$(OBJS)) -include $(patsubst %.gresource.xml,%.gresource.d,$(GRESOURCE_FILES)) package-update-indicator-5/pui-settings.c010064400017500001750000000033711353220474000173310ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define G_SETTINGS_ENABLE_BACKEND #include #include "pui-settings.h" #define SETTINGS_ROOT_PATH \ "/org/guido-berhoerster/code/package-update-indicator/" #define SETTINGS_ROOT_GROUP "General" GSettings * pui_settings_new(void) { gchar *settings_filename; GSettingsBackend *settings_backend; settings_filename = g_build_filename(g_get_user_config_dir(), PACKAGE, PACKAGE ".conf", NULL); settings_backend = g_keyfile_settings_backend_new(settings_filename, SETTINGS_ROOT_PATH, SETTINGS_ROOT_GROUP); return (g_settings_new_with_backend(SETTINGS_SCHEMA_ID, settings_backend)); } package-update-indicator-5/pui-common.h010064400017500001750000000032651353220474000167700ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PUI_COMMON_H #define PUI_COMMON_H G_BEGIN_DECLS #ifndef PUI_STARTUP_DELAY #define PUI_STARTUP_DELAY (3 * 60) #endif /* !PUI_STARTUP_DELAY */ #ifndef PUI_UPDATES_CHANGED_DELAY #define PUI_UPDATES_CHANGED_DELAY (30) #endif /* !PUI_UPDATES_CHANGED_DELAY */ #ifndef PUI_CHECK_UPDATES_INTERVAL #define PUI_CHECK_UPDATES_INTERVAL (60 * 60) #endif /* !PUI_CHECK_UPDATES_INTERVAL */ #ifndef PUI_DEFAULT_REFRESH_INTERVAL #define PUI_DEFAULT_REFRESH_INTERVAL (24 * 60 * 60) #endif /* !PUI_DEFAULT_REFRESH_INTERVAL */ G_END_DECLS #endif /* !PUI_COMMON_H */ package-update-indicator-5/examples004075500017500001750000000000001353220474000162705ustar00gbergberpackage-update-indicator-5/examples/10_vendor_update_command.gschema.override010064400017500001750000000001421353220474000263450ustar00gbergber[org.guido-berhoerster.code.package-update-indicator] update-command='/usr/bin/gpk-update-viewer' package-update-indicator-5/pui-about-dialog.ui010064400017500001750000000035711353220474000202350ustar00gbergber False About Package Update Indicator system-software-update dialog Package Update Indicator Copyright © 2018 Guido Berhörster Notify about available software updates http://code.guido-berhoerster.org/projects/package-update-indicator/ Guido Berhörster Translator system-software-update True mit-x11 False vertical 2 False end False False 0 package-update-indicator-5/po004075500017500001750000000000001353220474000150705ustar00gbergberpackage-update-indicator-5/po/POTFILES.in010064400017500001750000000006421353220474000167230ustar00gbergberorg.guido-berhoerster.code.package-update-indicator.desktop.in org.guido-berhoerster.code.package-update-indicator.gschema.xml org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in package-update-indicator-prefs.c package-update-indicator.c pui-about-dialog.ui pui-application.c pui-backend.c pui-get-updates.c pui-menu.ui pui-prefs-application.c pui-prefs-window.ui pui-settings.c pui-types.c.in package-update-indicator-5/po/en.po010064400017500001750000000150341353220474000161110ustar00gbergber# English translations for package-update-indicator package. # Copyright (C) 2018 Guido Berhoerster # This file is distributed under the same license as the package-update-indicator package. # Guido Berhoerster , 2018. # msgid "" msgstr "" "Project-Id-Version: package-update-indicator 1\n" "Report-Msgid-Bugs-To: guido+pui@berhoerster.name\n" "POT-Creation-Date: 2018-12-08 08:50+0000\n" "PO-Revision-Date: 2018-07-06 12:10+0000\n" "Last-Translator: Guido Berhoerster \n" "Language-Team: none\n" "Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:3 #: org.guido-berhoerster.code.package-update-indicator.desktop.in:4 #: package-update-indicator.c:59 pui-application.c:489 msgid "Package Update Indicator" msgstr "Package Update Indicator" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:5 #: pui-about-dialog.ui:12 msgid "Notify about available software updates" msgstr "Notify about available software updates" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:6 msgid "system-software-update" msgstr "system-software-update" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:7 msgid "Update command" msgstr "Update command" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:8 msgid "Command for installing updates." msgstr "Command for installing updates." #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:12 msgid "Refresh interval" msgstr "Refresh interval" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:13 msgid "The interval in seconds for refreshing metadata." msgstr "The interval in seconds for refreshing metadata." #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:18 msgid "Whether to use a mobile connection" msgstr "Whether to use a mobile connection" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:19 msgid "If enabled, use a mobile connection refreshing the package cache." msgstr "If enabled, use a mobile connection refreshing the package cache." #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:3 #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:4 #: package-update-indicator-prefs.c:43 msgid "Package Update Indicator Preferences" msgstr "Package Update Indicator Preferences" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:5 msgid "Edit the Preferences for Package Update Indicator" msgstr "Edit the Preferences for Package Update Indicator" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:6 msgid "updates;preferences;" msgstr "updates;preferences;" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:7 msgid "preferences-other" msgstr "preferences-other" #: pui-about-dialog.ui:7 msgid "About Package Update Indicator" msgstr "About Package Update Indicator" #: pui-about-dialog.ui:11 msgid "Copyright © 2018 Guido Berhörster" msgstr "Copyright © 2018 Guido Berhörster" #. Place your name here. #: pui-about-dialog.ui:15 msgid "Translator" msgstr "Translator" #: pui-application.c:73 msgid "Enable debugging messages" msgstr "Enable debugging messages" #: pui-application.c:75 msgid "Quit running instance of Package Update Indicator" msgstr "Quit running instance of Package Update Indicator" #: pui-application.c:77 msgid "Print the version number and quit" msgstr "Print the version number and quit" #: pui-application.c:232 msgid "Up to Date" msgstr "Up to Date" #: pui-application.c:233 msgid "The system is up to date." msgstr "The system is up to date." #: pui-application.c:236 msgid "Software Update" msgid_plural "Software Updates" msgstr[0] "Software Update" msgstr[1] "Software Updates" #: pui-application.c:239 msgid "There is a software update available." msgstr "There is a software update available." #: pui-application.c:242 #, c-format msgid "There are %u software updates available." msgstr "There are %u software updates available." #: pui-application.c:247 msgid "Important Software Update" msgid_plural "Important Software Updates" msgstr[0] "Important Software Update" msgstr[1] "Important Software Updates" #: pui-application.c:250 msgid "There is an important software update available." msgstr "There is an important software update available." #: pui-application.c:253 #, c-format msgid "There are %u important software updates available." msgstr "There are %u important software updates available." #: pui-application.c:257 #, c-format msgid "There are %u software updates available, one of them is important." msgstr "There are %u software updates available, one of them is important." #: pui-application.c:262 #, c-format msgid "There are %u software updates available, %u of them are important." msgstr "There are %u software updates available, %u of them are important." #: pui-application.c:270 msgid "Logout Required" msgstr "Logout Required" #: pui-application.c:271 msgid "You need to log out and back in for the update to take effect." msgstr "You need to log out and back in for the update to take effect." #: pui-application.c:275 msgid "Restart Required" msgstr "Restart Required" #: pui-application.c:276 msgid "The computer has to be restarted for the updates to take effect." msgstr "The computer has to be restarted for the updates to take effect." #: pui-application.c:324 msgid "Install Updates" msgstr "Install Updates" #: pui-application.c:434 msgid "Update notifications are not supported." msgstr "Update notifications are not supported." #: pui-menu.ui:13 msgid "_Install updates" msgstr "_Install updates" #: pui-menu.ui:22 msgid "_Preferences…" msgstr "_Preferences…" #: pui-menu.ui:31 msgid "_About…" msgstr "_About…" #: pui-prefs-window.ui:17 msgid "always" msgstr "always" #: pui-prefs-window.ui:22 msgid "every hour" msgstr "every hour" #: pui-prefs-window.ui:27 msgid "every 8 hours" msgstr "every 8 hours" #: pui-prefs-window.ui:32 msgid "twice a day" msgstr "twice a day" #: pui-prefs-window.ui:37 msgid "daily" msgstr "daily" #: pui-prefs-window.ui:42 msgid "weekly" msgstr "weekly" #: pui-prefs-window.ui:47 msgid "never" msgstr "never" #: pui-prefs-window.ui:76 msgid "_Refresh cache:" msgstr "_Refresh cache:" #: pui-prefs-window.ui:89 msgid "_Command for installing updates:" msgstr "_Command for installing updates:" #: pui-prefs-window.ui:130 msgid "Use _mobile connection" msgstr "Use _mobile connection" package-update-indicator-5/po/LINGUAS010064400017500001750000000000111353220474000161610ustar00gbergberde en id package-update-indicator-5/po/de.po010064400017500001750000000155541353220474000161060ustar00gbergber# German translations for package-update-indicator package. # Copyright (C) 2018 Guido Berhoerster # This file is distributed under the same license as the package-update-indicator package. # Guido Berhoerster , 2018. # msgid "" msgstr "" "Project-Id-Version: package-update-indicator 1\n" "Report-Msgid-Bugs-To: guido+pui@berhoerster.name\n" "POT-Creation-Date: 2018-12-08 08:50+0000\n" "PO-Revision-Date: 2018-07-06 12:10+0000\n" "Last-Translator: Guido Berhoerster \n" "Language-Team: none\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:3 #: org.guido-berhoerster.code.package-update-indicator.desktop.in:4 #: package-update-indicator.c:59 pui-application.c:489 msgid "Package Update Indicator" msgstr "Paketaktualisierungsanzeige" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:5 #: pui-about-dialog.ui:12 msgid "Notify about available software updates" msgstr "Benachrichtigung über verfügbare Softwareaktualisierungen" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:6 msgid "system-software-update" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:7 msgid "Update command" msgstr "Aktualisierungsbefehl" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:8 msgid "Command for installing updates." msgstr "Befehl zu Installieren von Aktualisierungen." #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:12 msgid "Refresh interval" msgstr "Aktualisierungsintervall" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:13 msgid "The interval in seconds for refreshing metadata." msgstr "Das Aktualisierungsintervall für Metadaten." #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:18 msgid "Whether to use a mobile connection" msgstr "Ob eine Mobilfunkverbindung benutzt werden kann" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:19 msgid "If enabled, use a mobile connection refreshing the package cache." msgstr "" "Wenn aktiviert, wird der Paket-Cache über eine mobile Verbindung " "aktualisiert." #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:3 #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:4 #: package-update-indicator-prefs.c:43 msgid "Package Update Indicator Preferences" msgstr "Einstellungen der Paketaktualisierungsanzeige" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:5 msgid "Edit the Preferences for Package Update Indicator" msgstr "Bearbeite Einstellungen der Paketaktualisierungsanzeige" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:6 msgid "updates;preferences;" msgstr "Aktualisierungen;Updates;Einstellungen;" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:7 msgid "preferences-other" msgstr "" #: pui-about-dialog.ui:7 msgid "About Package Update Indicator" msgstr "Über Paketaktualisierungsanzeige" #: pui-about-dialog.ui:11 msgid "Copyright © 2018 Guido Berhörster" msgstr "Copyright © 2018 Guido Berhörster" #. Place your name here. #: pui-about-dialog.ui:15 msgid "Translator" msgstr "Guido Berhörster" #: pui-application.c:73 msgid "Enable debugging messages" msgstr "Debugging-Nachrichten aktivieren" #: pui-application.c:75 msgid "Quit running instance of Package Update Indicator" msgstr "Beende laufende Instanz der Paketaktualisierungsanzeige" #: pui-application.c:77 msgid "Print the version number and quit" msgstr "Versionsnummer zeigen und beenden" #: pui-application.c:232 msgid "Up to Date" msgstr "Auf dem neuesten Stand" #: pui-application.c:233 msgid "The system is up to date." msgstr "Das System ist auf dem neuesten Stand" #: pui-application.c:236 msgid "Software Update" msgid_plural "Software Updates" msgstr[0] "Softwareaktualisierung" msgstr[1] "Softwareaktualisierungen" #: pui-application.c:239 msgid "There is a software update available." msgstr "Es ist eine Softwareaktualisierung verfügbar." #: pui-application.c:242 #, c-format msgid "There are %u software updates available." msgstr "Es sind %u Softwareaktualisierungen verfügbar." #: pui-application.c:247 msgid "Important Software Update" msgid_plural "Important Software Updates" msgstr[0] "Wichtige Softwareaktualisierung" msgstr[1] "Wichtige Softwareaktualisierungen" #: pui-application.c:250 msgid "There is an important software update available." msgstr "Es ist eine wichtige Softwareaktualisierung verfügbar." #: pui-application.c:253 #, c-format msgid "There are %u important software updates available." msgstr "Es sind %u wichtige Softwareaktualisierungen verfügbar." #: pui-application.c:257 #, c-format msgid "There are %u software updates available, one of them is important." msgstr "Es sind %u Softwareaktualisierungen verfügbar, eine davon ist wichtig." #: pui-application.c:262 #, c-format msgid "There are %u software updates available, %u of them are important." msgstr "Es sind %u Softwareaktualisierungen verfügbar, %u davon sind wichtig." #: pui-application.c:270 msgid "Logout Required" msgstr "Abmeldung erforderlich" #: pui-application.c:271 msgid "You need to log out and back in for the update to take effect." msgstr "" "Sie müssen sich aus- und wieder einloggen, damit die Aktualisierung wirksam wird." #: pui-application.c:275 msgid "Restart Required" msgstr "Neutstart Erforderlich" #: pui-application.c:276 msgid "The computer has to be restarted for the updates to take effect." msgstr "" "Der Computer muss neu gestarte werden damit die Aktualisierungen wirksam werden." #: pui-application.c:324 msgid "Install Updates" msgstr "Installiere Aktualisierungen" #: pui-application.c:434 msgid "Update notifications are not supported." msgstr "Aktualisierungsbenachrichtigungen werden nicht unterstützt." #: pui-menu.ui:13 msgid "_Install updates" msgstr "_Installiere Aktualisierungen" #: pui-menu.ui:22 msgid "_Preferences…" msgstr "_Einstellungen…" #: pui-menu.ui:31 msgid "_About…" msgstr "Ü_ber…" #: pui-prefs-window.ui:17 msgid "always" msgstr "immer" #: pui-prefs-window.ui:22 msgid "every hour" msgstr "einmal die Stunde" #: pui-prefs-window.ui:27 msgid "every 8 hours" msgstr "alle 8 Stunden" #: pui-prefs-window.ui:32 msgid "twice a day" msgstr "zweimal täglich" #: pui-prefs-window.ui:37 msgid "daily" msgstr "täglich" #: pui-prefs-window.ui:42 msgid "weekly" msgstr "wöchentlich" #: pui-prefs-window.ui:47 msgid "never" msgstr "nie" #: pui-prefs-window.ui:76 msgid "_Refresh cache:" msgstr "Cache _aktualisieren:" #: pui-prefs-window.ui:89 msgid "_Command for installing updates:" msgstr "_Befehl zum Installieren von Aktualisierungen:" #: pui-prefs-window.ui:130 msgid "Use _mobile connection" msgstr "Benutze _Mobilfunkverbindung" package-update-indicator-5/po/id.po010064400017500001750000000145041353220474000161040ustar00gbergber# Indonesian translations for package-update-indicator package. # Copyright (C) 2018 Guido Berhoerster # This file is distributed under the same license as the package-update-indicator package. # Guido Berhoerster , 2018. # msgid "" msgstr "" "Project-Id-Version: package-update-indicator 1\n" "Report-Msgid-Bugs-To: guido+pui@berhoerster.name\n" "POT-Creation-Date: 2018-12-08 08:50+0000\n" "PO-Revision-Date: 2018-07-06 12:10+0000\n" "Last-Translator: Guido Berhoerster \n" "Language-Team: none\n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:3 #: org.guido-berhoerster.code.package-update-indicator.desktop.in:4 #: package-update-indicator.c:59 pui-application.c:489 msgid "Package Update Indicator" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:5 #: pui-about-dialog.ui:12 msgid "Notify about available software updates" msgstr "Pemberitahuan tentang pembaharuan-pembaharuan perangkat lunak" #: org.guido-berhoerster.code.package-update-indicator.desktop.in:6 msgid "system-software-update" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:7 msgid "Update command" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:8 msgid "Command for installing updates." msgstr "Perintah untuk pasang perangkat lunak pembaharuan-pembaharuan." #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:12 msgid "Refresh interval" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:13 msgid "The interval in seconds for refreshing metadata." msgstr "" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:18 msgid "Whether to use a mobile connection" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.gschema.xml:19 msgid "If enabled, use a mobile connection refreshing the package cache." msgstr "" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:3 #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:4 #: package-update-indicator-prefs.c:43 msgid "Package Update Indicator Preferences" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:5 msgid "Edit the Preferences for Package Update Indicator" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:6 msgid "updates;preferences;" msgstr "" #: org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in:7 msgid "preferences-other" msgstr "" #: pui-about-dialog.ui:7 msgid "About Package Update Indicator" msgstr "" #: pui-about-dialog.ui:11 msgid "Copyright © 2018 Guido Berhörster" msgstr "Copyright © 2018 Guido Berhörster" #. Place your name here. #: pui-about-dialog.ui:15 msgid "Translator" msgstr "Guido Berhörster" #: pui-application.c:73 msgid "Enable debugging messages" msgstr "" #: pui-application.c:75 msgid "Quit running instance of Package Update Indicator" msgstr "" #: pui-application.c:77 msgid "Print the version number and quit" msgstr "Tampilkan nomor versi dan keluar" #: pui-application.c:232 msgid "Up to Date" msgstr "Up-to-date" #: pui-application.c:233 msgid "The system is up to date." msgstr "Sistemnya telah up-to-date." #: pui-application.c:236 msgid "Software Update" msgid_plural "Software Updates" msgstr[0] "Pembaharuan Perangkat Lunak" msgstr[1] "Pembaharuan-Pembaharuan Perangkat Lunak" #: pui-application.c:239 msgid "There is a software update available." msgstr "Tersedia satu pembaharuan perangkat lunak." #: pui-application.c:242 #, c-format msgid "There are %u software updates available." msgstr "Tersedia %u pembaharuan-pembaharuan perangkat lunak." #: pui-application.c:247 msgid "Important Software Update" msgid_plural "Important Software Updates" msgstr[0] "Perangkat Lunak Pembaharuan yang penting" msgstr[1] "Perangkat Lunak Pembaharuan-Pembaharuan yang penting" #: pui-application.c:250 msgid "There is an important software update available." msgstr "Tersedia satu pembaharuan perangkat lunak yang penting." #: pui-application.c:253 #, c-format msgid "There are %u important software updates available." msgstr "Tersedia %u pembaharuan-pembaharuan perangkat lunak yang penting." #: pui-application.c:257 #, c-format msgid "There are %u software updates available, one of them is important." msgstr "" "Tersedia %u pembaharuan-pembaharuan perangkat lunak, diantaranya satu yang " "penting." #: pui-application.c:262 #, c-format msgid "There are %u software updates available, %u of them are important." msgstr "" "Tersedia %u pembaharuan-pembaharuan perangkat lunak, diantaranya %u yang " "penting." #: pui-application.c:270 msgid "Logout Required" msgstr "Diperlukan Log Keluar" #: pui-application.c:271 msgid "You need to log out and back in for the update to take effect." msgstr "" #: pui-application.c:275 msgid "Restart Required" msgstr "Diperlukan Reboot" #: pui-application.c:276 msgid "The computer has to be restarted for the updates to take effect." msgstr "" #: pui-application.c:324 msgid "Install Updates" msgstr "Pasang Perangkat Lunak Pembaharuan-Pembaharuan" #: pui-application.c:434 msgid "Update notifications are not supported." msgstr "Pemberitahuan pembaharuan-pembaharuan tidak didukung." #: pui-menu.ui:13 msgid "_Install updates" msgstr "_Pasang Perangkat Lunak Pembaharuan-Pembaharuan" #: pui-menu.ui:22 msgid "_Preferences…" msgstr "_Preferensi…" #: pui-menu.ui:31 msgid "_About…" msgstr "_Tentang…" #: pui-prefs-window.ui:17 msgid "always" msgstr "selalu" #: pui-prefs-window.ui:22 msgid "every hour" msgstr "setiap jam" #: pui-prefs-window.ui:27 msgid "every 8 hours" msgstr "setiap 8 jam" #: pui-prefs-window.ui:32 msgid "twice a day" msgstr "dua kali sehari" #: pui-prefs-window.ui:37 msgid "daily" msgstr "setiap hari" #: pui-prefs-window.ui:42 msgid "weekly" msgstr "setiap minggu" #: pui-prefs-window.ui:47 msgid "never" msgstr "tak pernah" #: pui-prefs-window.ui:76 msgid "_Refresh cache:" msgstr "" #: pui-prefs-window.ui:89 msgid "_Command for installing updates:" msgstr "_Perintah untuk pasang perangkat lunak pembaharuan-pembaharuan:" #: pui-prefs-window.ui:130 msgid "Use _mobile connection" msgstr "Pakai sambungan data _seluler" package-update-indicator-5/pui-prefs.gresource.xml010064400017500001750000000003401353220474000211540ustar00gbergber pui-prefs-window.ui package-update-indicator-5/pui-types.h.in010064400017500001750000000010371353220474000172440ustar00gbergber/*** BEGIN file-header ***/ #ifndef PUI_TYPES_H #define PUI_TYPES_H #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) GType @enum_name@_get_type(void) G_GNUC_CONST; /*** END value-header ***/ /*** BEGIN file-tail ***/ gchar * pui_types_enum_to_string(GType, gint); G_END_DECLS #endif /* !PUI_TYPES_H */ /*** END file-tail ***/ package-update-indicator-5/NEWS010064400017500001750000000031401353220474000152230ustar00gbergberNews ==== package-update-indicator 5 (2019-08-30T13:32:52+02:00) ------------------------------------------------------ - Reduce delay before checking for updates after an "updates-changed" signal - Fix continuos loop of update checks if the refresh cache interval is 0 - Add fallback icons for KDE-based themes package-update-indicator 4 (2019-07-24T16:27:25+02:00) ------------------------------------------------------ - Fix support for libayatana-appindicator package-update-indicator 3 (2019-07-24T10:33:37+02:00) ------------------------------------------------------ - Use consistent vocabulary in German translations - Add support for libayantana-indicator - Fix typo in German translations - Add missing changelog entries package-update-indicator 2 (2018-12-08T10:09:35+01:00) ------------------------------------------------------ - Add keywords to desktop files - Fix typo in notification message - Do not run glib-compile-schemas if schemas are installed into staging directory - Set application indicator title - Add note for vendors on how to override default settings package-update-indicator 1 (2018-07-06T14:21:28+02:00) ------------------------------------------------------ - Notify about required session or system restarts - Add Indonesian translations - Add German translations - Add English translations - Make PackagKit use the user's network proxies - Do not check for updates if the battery is low - Add setting to control whether to use a mobile connection - Add menu item to launch the preferences application - Use GtkBuilder for all widgets - Add preferences application - Initial revision package-update-indicator-5/pui-get-updates.h010064400017500001750000000033411353220474000177150ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PUI_GET_UPDATES_H #define PUI_GET_UPDATES_H #include #include #include G_BEGIN_DECLS #define PUI_GET_UPDATES_ERROR (pui_get_updates_error_quark()) enum { PUI_GET_UPDATES_ERROR_REFRESH_FAILED, PUI_GET_UPDATES_ERROR_GET_UPDATES_FAILED, PUI_GET_UPDATES_ERROR_CANCELLED }; GQuark pui_get_updates_error_quark(void); void pui_get_updates_async(PkControl *, guint, GCancellable *, GAsyncReadyCallback, gpointer); GPtrArray * pui_get_updates_finish(GAsyncResult *, GError **); G_END_DECLS #endif /* !PUI_GET_UPDATES_H */ package-update-indicator-5/pui-prefs-window.ui010064400017500001750000000156701353220474000203150ustar00gbergber always always 0 one-hour every hour 3600 eight-hours every 8 hours 28800 twelve-hours twice a day 43200 one-day daily 86400 one-week weekly 604800 never never 4294967295 False False True False 18 18 18 18 vertical 18 True False 18 12 True False end _Refresh cache: True 0 0 True False end _Command for installing updates: True update-command 0 1 True True 32 1 1 True False refresh-interval-list 0 1 1 0 Use _mobile connection True True False True True 0 2 2 True True 0 True False end gtk-close True True True app.quit True True True 0 False True 1 org.guido-berhoerster.code.package-update-indicator.preferences.desktop.in010064400017500001750000000005271353220474000327270ustar00gbergberpackage-update-indicator-5[Desktop Entry] Name=Package Update Indicator Preferences GenericName=Package Update Indicator Preferences Comment=Edit the Preferences for Package Update Indicator Keywords=updates;preferences; Icon=preferences-other Exec=package-update-indicator-prefs Terminal=false Type=Application Categories=Settings;PackageManager;GTK; NotShowIn=GNOME; package-update-indicator-5/pui.gresource.xml010064400017500001750000000004031353220474000200370ustar00gbergber pui-menu.ui pui-about-dialog.ui package-update-indicator-5/package-update-indicator.c010064400017500001750000000043721353220474000215250ustar00gbergber/* * Copyright (C) 2018 Guido Berhoerster * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "pui-application.h" gboolean restart; int main(int argc, char *argv[]) { int status; gchar *program; PuiApplication *application; /* try to obtain the name of the executable for safe re-execution */ if (argv[0] == NULL) { g_error("unable to locate %s executable", PACKAGE); } if (argv[0][0] != '/') { program = g_find_program_in_path(argv[0]); if (program == NULL) { g_error("unable to locate %s executable", PACKAGE); } argv[0] = program; } bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); setlocale(LC_ALL, ""); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); g_set_application_name(_("Package Update Indicator")); gtk_init(&argc, &argv); application = pui_application_new(); status = g_application_run(G_APPLICATION(application), argc, argv); g_object_unref(application); if (restart) { /* application restart requested */ if (execv(argv[0], argv) == -1) { g_error("exec: %s", g_strerror(errno)); } } exit(status); }