Graphical package manager for pacman based on pamac 5.x.x
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

349 lines
9.8KB

  1. /*
  2. * pamac-vala
  3. *
  4. * Copyright (C) 2014-2016 Guillaume Benoit <guillaume@manjaro.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a get of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. // i18n
  20. const string GETTEXT_PACKAGE = "pamac";
  21. const string update_icon_name = "pamac-tray-update";
  22. const string noupdate_icon_name = "pamac-tray-no-update";
  23. const string noupdate_info = _("Your system is up-to-date");
  24. namespace Pamac {
  25. [DBus (name = "org.manjaro.pamac")]
  26. interface Daemon : Object {
  27. public abstract string get_lockfile () throws IOError;
  28. public abstract void start_refresh (bool force) throws IOError;
  29. public abstract void start_get_updates (bool check_aur_updates) throws IOError;
  30. [DBus (no_reply = true)]
  31. public abstract void quit () throws IOError;
  32. public signal void get_updates_finished (Updates updates);
  33. public signal void write_pamac_config_finished (bool recurse, uint64 refresh_period, bool no_update_hide_icon,
  34. bool enable_aur, bool search_aur, bool check_aur_updates,
  35. bool no_confirm_build);
  36. public signal void write_alpm_config_finished (bool checkspace);
  37. }
  38. class TrayIcon: Gtk.Application {
  39. Notify.Notification notification;
  40. //~ Notification notification;
  41. Daemon daemon;
  42. bool extern_lock;
  43. uint refresh_timeout_id;
  44. Gtk.StatusIcon status_icon;
  45. Gtk.Menu menu;
  46. GLib.File lockfile;
  47. public TrayIcon () {
  48. application_id = "org.manjaro.pamac.tray";
  49. flags = ApplicationFlags.FLAGS_NONE;
  50. }
  51. void start_daemon () {
  52. try {
  53. daemon = Bus.get_proxy_sync (BusType.SYSTEM, "org.manjaro.pamac", "/org/manjaro/pamac");
  54. // Connecting to signals
  55. daemon.get_updates_finished.connect (on_get_updates_finished);
  56. daemon.write_pamac_config_finished.connect (on_write_pamac_config_finished);
  57. daemon.write_alpm_config_finished.connect (on_write_alpm_config_finished);
  58. } catch (IOError e) {
  59. stderr.printf ("IOError: %s\n", e.message);
  60. }
  61. }
  62. void stop_daemon () {
  63. if (!check_pamac_running ()) {
  64. try {
  65. daemon.quit ();
  66. } catch (IOError e) {
  67. stderr.printf ("IOError: %s\n", e.message);
  68. }
  69. }
  70. }
  71. // Create menu for right button
  72. void create_menu () {
  73. menu = new Gtk.Menu ();
  74. Gtk.MenuItem item;
  75. item = new Gtk.MenuItem.with_label (_("Update Manager"));
  76. item.activate.connect (execute_updater);
  77. menu.append (item);
  78. item = new Gtk.MenuItem.with_label (_("Package Manager"));
  79. item.activate.connect (execute_manager);
  80. menu.append (item);
  81. item = new Gtk.MenuItem.with_mnemonic (_("_Quit"));
  82. item.activate.connect (this.release);
  83. menu.append (item);
  84. menu.show_all ();
  85. }
  86. // Show popup menu on right button
  87. void menu_popup (uint button, uint time) {
  88. menu.popup (null, null, null, button, time);
  89. }
  90. void left_clicked () {
  91. if (status_icon.icon_name == "pamac-tray-update") {
  92. execute_updater ();
  93. }
  94. }
  95. void execute_updater () {
  96. try {
  97. Process.spawn_command_line_async ("pamac-updater");
  98. } catch (SpawnError e) {
  99. stderr.printf ("SpawnError: %s\n", e.message);
  100. }
  101. }
  102. void execute_manager () {
  103. try {
  104. Process.spawn_command_line_async ("pamac-manager");
  105. } catch (SpawnError e) {
  106. stderr.printf ("SpawnError: %s\n", e.message);
  107. }
  108. }
  109. public void update_icon (string icon, string info) {
  110. status_icon.set_from_icon_name (icon);
  111. status_icon.set_tooltip_markup (info);
  112. }
  113. bool start_refresh () {
  114. // if pamac is not running start refresh else just check updates
  115. if (check_pamac_running ()) {
  116. check_updates ();
  117. } else {
  118. try {
  119. daemon.start_refresh (false);
  120. } catch (IOError e) {
  121. stderr.printf ("IOError: %s\n", e.message);
  122. }
  123. }
  124. return true;
  125. }
  126. void on_write_pamac_config_finished (bool recurse, uint64 refresh_period) {
  127. launch_refresh_timeout (refresh_period);
  128. if (refresh_period == 0) {
  129. status_icon.visible = false;
  130. } else {
  131. check_updates ();
  132. }
  133. }
  134. void on_write_alpm_config_finished (bool checkspace) {
  135. check_updates ();
  136. }
  137. void on_get_updates_finished (Updates updates) {
  138. uint updates_nb = updates.repos_updates.length + updates.aur_updates.length;
  139. if (updates_nb == 0) {
  140. this.update_icon (noupdate_icon_name, noupdate_info);
  141. var pamac_config = new Pamac.Config ("/etc/pamac.conf");
  142. if (pamac_config.no_update_hide_icon) {
  143. status_icon.visible = false;
  144. } else {
  145. status_icon.visible = true;
  146. }
  147. close_notification();
  148. } else {
  149. string info = ngettext ("%u available update", "%u available updates", updates_nb).printf (updates_nb);
  150. this.update_icon (update_icon_name, info);
  151. status_icon.visible = true;
  152. if (check_pamac_running ()) {
  153. update_notification (info);
  154. } else {
  155. show_notification (info);
  156. }
  157. }
  158. stop_daemon ();
  159. }
  160. void check_updates () {
  161. var pamac_config = new Pamac.Config ("/etc/pamac.conf");
  162. if (pamac_config.refresh_period == 0) {
  163. return;
  164. }
  165. try {
  166. daemon.start_get_updates (pamac_config.enable_aur && pamac_config.check_aur_updates);
  167. } catch (IOError e) {
  168. stderr.printf ("IOError: %s\n", e.message);
  169. }
  170. }
  171. void show_notification (string info) {
  172. //~ notification = new Notification (_("Update Manager"));
  173. //~ notification.set_body (info);
  174. //~ Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
  175. //~ Gdk.Pixbuf icon = icon_theme.load_icon ("system-software-update", 32, 0);
  176. //~ notification.set_icon (icon);
  177. //~ var action = new SimpleAction ("update", null);
  178. //~ action.activate.connect (execute_updater);
  179. //~ this.add_action (action);
  180. //~ notification.add_button (_("Show available updates"), "app.update");
  181. //~ notification.set_default_action ("app.update");
  182. //~ this.send_notification (_("Update Manager"), notification);
  183. try {
  184. close_notification();
  185. notification = new Notify.Notification (_("Update Manager"), info, "system-software-update");
  186. notification.add_action ("default", _("Show available updates"), execute_updater);
  187. notification.show ();
  188. } catch (Error e) {
  189. stderr.printf ("Notify Error: %s", e.message);
  190. }
  191. }
  192. void update_notification (string info) {
  193. try {
  194. if (notification != null) {
  195. if (notification.get_closed_reason() == -1 && notification.body != info) {
  196. notification.update (_("Update Manager"), info, "system-software-update");
  197. notification.show ();
  198. }
  199. } else {
  200. show_notification (info);
  201. }
  202. } catch (Error e) {
  203. stderr.printf ("Notify Error: %s", e.message);
  204. }
  205. }
  206. void close_notification () {
  207. try {
  208. if (notification != null) {
  209. notification.close();
  210. notification = null;
  211. }
  212. } catch (Error e) {
  213. stderr.printf ("Notify Error: %s", e.message);
  214. }
  215. }
  216. bool check_pamac_running () {
  217. Application app;
  218. bool run = false;
  219. app = new Application ("org.manjaro.pamac.manager", 0);
  220. try {
  221. app.register ();
  222. } catch (GLib.Error e) {
  223. stderr.printf ("%s\n", e.message);
  224. }
  225. run = app.get_is_remote ();
  226. if (run) {
  227. return run;
  228. }
  229. app = new Application ("org.manjaro.pamac.updater", 0);
  230. try {
  231. app.register ();
  232. } catch (GLib.Error e) {
  233. stderr.printf ("%s\n", e.message);
  234. }
  235. run = app.get_is_remote ();
  236. if (run) {
  237. return run;
  238. }
  239. app = new Application ("org.manjaro.pamac.install", 0);
  240. try {
  241. app.register ();
  242. } catch (GLib.Error e) {
  243. stderr.printf ("%s\n", e.message);
  244. }
  245. run = app.get_is_remote ();
  246. return run;
  247. }
  248. bool check_pacman_running () {
  249. if (extern_lock) {
  250. if (!lockfile.query_exists ()) {
  251. extern_lock = false;
  252. // let the time to the daemon to update packages
  253. Timeout.add (1000, () => {
  254. check_updates ();
  255. return false;
  256. });
  257. }
  258. } else {
  259. if (lockfile.query_exists ()) {
  260. extern_lock = true;
  261. }
  262. }
  263. return true;
  264. }
  265. void launch_refresh_timeout (uint64 refresh_period_in_hours) {
  266. if (refresh_timeout_id != 0) {
  267. Source.remove (refresh_timeout_id);
  268. refresh_timeout_id = 0;
  269. }
  270. if (refresh_period_in_hours != 0) {
  271. refresh_timeout_id = Timeout.add_seconds ((uint) refresh_period_in_hours*3600, start_refresh);
  272. }
  273. }
  274. public override void startup () {
  275. // i18n
  276. Intl.textdomain ("pamac");
  277. Intl.setlocale (LocaleCategory.ALL, "");
  278. var pamac_config = new Pamac.Config ("/etc/pamac.conf");
  279. // if refresh period is 0, just return so tray will exit
  280. if (pamac_config.refresh_period == 0) {
  281. return;
  282. }
  283. base.startup ();
  284. extern_lock = false;
  285. refresh_timeout_id = 0;
  286. status_icon = new Gtk.StatusIcon ();
  287. status_icon.visible = !(pamac_config.no_update_hide_icon);
  288. update_icon (noupdate_icon_name, noupdate_info);
  289. status_icon.activate.connect (left_clicked);
  290. create_menu ();
  291. status_icon.popup_menu.connect (menu_popup);
  292. Notify.init (_("Update Manager"));
  293. start_daemon ();
  294. try {
  295. lockfile = GLib.File.new_for_path (daemon.get_lockfile ());
  296. } catch (IOError e) {
  297. stderr.printf ("IOError: %s\n", e.message);
  298. //try standard lock file
  299. lockfile = GLib.File.new_for_path ("var/lib/pacman/db.lck");
  300. }
  301. Timeout.add (200, check_pacman_running);
  302. start_refresh ();
  303. launch_refresh_timeout (pamac_config.refresh_period);
  304. this.hold ();
  305. }
  306. public override void activate () {
  307. // nothing to do
  308. }
  309. static int main (string[] args) {
  310. var tray_icon = new TrayIcon();
  311. return tray_icon.run (args);
  312. }
  313. }
  314. }