/* * pamac-vala * * Copyright (C) 2014-2019 Guillaume Benoit <guillaume@manjaro.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a get of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ namespace Pamac { string search_string; List<string> repos_names; GenericSet<string?> to_install; GenericSet<string?> to_remove; GenericSet<string?> to_load; GenericSet<string?> to_build; GenericSet<string?> to_update; GenericSet<string?> temporary_ignorepkgs; int sort_pkgs_by_relevance (Package pkg_a, Package pkg_b) { if (pkg_a.name in to_remove) { if (pkg_b.name in to_remove) { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return -1; } } if (pkg_b.name in to_remove) { if (pkg_a.name in to_remove) { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_a.name in to_install) { if (pkg_b.name in to_install) { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return -1; } } if (pkg_b.name in to_install) { if (pkg_a.name in to_install) { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_a.name in temporary_ignorepkgs) { if (pkg_b.name in temporary_ignorepkgs) { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return -1; } } if (pkg_b.name in temporary_ignorepkgs) { if (pkg_a.name in temporary_ignorepkgs) { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_a.installed_version == "") { if (pkg_b.installed_version == "") { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_b.installed_version == "") { if (pkg_a.installed_version == "") { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return -1; } } if (pkg_a.app_name == "") { if (pkg_b.app_name == "") { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_b.app_name == "") { if (pkg_a.app_name == "") { return sort_pkgs_by_name (pkg_a, pkg_b); } else { return -1; } } return sort_pkgs_by_name (pkg_a, pkg_b); } int sort_pkgs_by_name (Package pkg_a, Package pkg_b) { string str_a = "%s%s".printf (pkg_a.app_name, pkg_a.name); string str_b = "%s%s".printf (pkg_b.app_name, pkg_b.name); return strcmp (str_a, str_b); } int sort_pkgs_by_date (Package pkg_a, Package pkg_b) { if (pkg_a.installed_version == "") { if (pkg_b.installed_version == "") { if (pkg_a.builddate > pkg_b.builddate) { return -1; } if (pkg_b.builddate > pkg_a.builddate) { return 1; } return sort_pkgs_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_b.installed_version == "") { if (pkg_a.installed_version == "") { if (pkg_a.builddate > pkg_b.builddate) { return -1; } if (pkg_b.builddate > pkg_a.builddate) { return 1; } return sort_pkgs_by_name (pkg_a, pkg_b); } else { return -1; } } if (pkg_a.installdate > pkg_b.installdate) { return -1; } if (pkg_b.installdate > pkg_a.installdate) { return 1; } return sort_pkgs_by_name (pkg_a, pkg_b); } int sort_pkgs_by_repo (Package pkg_a, Package pkg_b) { int index_a = -2; if (pkg_a.repo == dgettext (null, "AUR")) { index_a = -1; } else if (pkg_a.repo != "") { unowned List<string>? element = repos_names.find_custom (pkg_a.repo, strcmp); if (element != null) { index_a = repos_names.index (element.data); } } int index_b = -2; if (pkg_b.repo == dgettext (null, "AUR")) { index_b = -1; } else if (pkg_b.repo != "") { unowned List<string>? element = repos_names.find_custom (pkg_b.repo, strcmp); if (element != null) { index_b = repos_names.index (element.data); } } if (index_a > index_b) { return 1; } if (index_b > index_a) { return -1; } return sort_pkgs_by_name (pkg_a, pkg_b); } int sort_pkgs_by_size (Package pkg_a, Package pkg_b) { if (pkg_a.installed_size > pkg_b.installed_size) { return -1; } if (pkg_b.installed_size > pkg_a.installed_size) { return 1; } return sort_pkgs_by_name (pkg_a, pkg_b); } int sort_aur_by_relevance (AURPackage pkg_a, AURPackage pkg_b) { if (pkg_a.name in to_build) { if (pkg_b.name in to_build) { return sort_aur_by_name (pkg_a, pkg_b); } else { return -1; } } if (pkg_b.name in to_build) { if (pkg_a.name in to_build) { return sort_aur_by_name (pkg_a, pkg_b); } else { return 1; } } if (pkg_a.popularity > pkg_b.popularity) { return -1; } if (pkg_b.popularity > pkg_a.popularity) { return 1; } return sort_aur_by_name (pkg_a, pkg_b); } int sort_aur_by_name (AURPackage pkg_a, AURPackage pkg_b) { return strcmp (pkg_a.name, pkg_b.name); } int sort_aur_by_date (AURPackage pkg_a, AURPackage pkg_b) { if (pkg_a.outofdate > pkg_b.outofdate) { return 1; } if (pkg_b.outofdate > pkg_a.outofdate) { return -1; } if (pkg_a.lastmodified > pkg_b.lastmodified) { return -1; } if (pkg_b.lastmodified > pkg_a.lastmodified) { return 1; } return sort_aur_by_name (pkg_a, pkg_b); } [GtkTemplate (ui = "/org/manjaro/pamac/manager/manager_window.ui")] class ManagerWindow : Gtk.ApplicationWindow { // icons Gtk.IconTheme icon_theme; Gdk.Pixbuf? package_icon; // manager objects [GtkChild] Gtk.HeaderBar headerbar; [GtkChild] public Gtk.Stack main_stack; [GtkChild] Gtk.StackSwitcher main_stack_switcher; [GtkChild] Gtk.Button button_back; [GtkChild] Gtk.Label header_filter_label; [GtkChild] Gtk.ModelButton preferences_button; [GtkChild] Gtk.Box browse_box; [GtkChild] Gtk.ListBox packages_listbox; [GtkChild] Gtk.ListBox aur_listbox; [GtkChild] Gtk.Revealer sidebar_revealer; [GtkChild] Gtk.Stack filters_stack; [GtkChild] public Gtk.Stack browse_stack; [GtkChild] public Gtk.ToggleButton search_button; [GtkChild] Gtk.SearchBar searchbar; [GtkChild] public Gtk.ComboBoxText search_comboboxtext; [GtkChild] public Gtk.Entry search_entry; [GtkChild] Gtk.ListBox filters_listbox; [GtkChild] Gtk.ListBox categories_listbox; [GtkChild] Gtk.ListBox groups_listbox; [GtkChild] Gtk.ListBox installed_listbox; [GtkChild] Gtk.ListBox repos_listbox; [GtkChild] Gtk.Stack origin_stack; [GtkChild] Gtk.ListBox updates_listbox; [GtkChild] Gtk.ListBox pending_listbox; [GtkChild] Gtk.ListBox search_listbox; [GtkChild] Gtk.Button remove_all_button; [GtkChild] Gtk.Button install_all_button; [GtkChild] Gtk.Button ignore_all_button; [GtkChild] Gtk.Box sort_order_box; [GtkChild] Gtk.ComboBoxText sort_comboboxtext; [GtkChild] Gtk.ScrolledWindow packages_scrolledwindow; [GtkChild] Gtk.ScrolledWindow aur_scrolledwindow; [GtkChild] Gtk.Label updated_label; [GtkChild] Gtk.Label no_item_label; [GtkChild] Gtk.Label checking_label; [GtkChild] Gtk.Stack properties_stack; [GtkChild] Gtk.Box build_files_box; [GtkChild] Gtk.ListBox properties_listbox; [GtkChild] Gtk.Grid deps_grid; [GtkChild] Gtk.Grid details_grid; [GtkChild] Gtk.Label name_label; [GtkChild] Gtk.Image app_image; [GtkChild] Gtk.Image app_screenshot; [GtkChild] Gtk.Label desc_label; [GtkChild] Gtk.Label long_desc_label; [GtkChild] Gtk.Label link_label; [GtkChild] Gtk.Label licenses_label; [GtkChild] Gtk.Button launch_button; [GtkChild] Gtk.ToggleButton remove_togglebutton; [GtkChild] Gtk.ToggleButton reinstall_togglebutton; [GtkChild] Gtk.ToggleButton install_togglebutton; [GtkChild] Gtk.ToggleButton build_togglebutton; [GtkChild] Gtk.Button reset_files_button; [GtkChild] Gtk.TextView files_textview; [GtkChild] Gtk.Box transaction_infobox; [GtkChild] Gtk.Revealer transaction_infobox_revealer; [GtkChild] Gtk.Button details_button; [GtkChild] Gtk.Button apply_button; [GtkChild] Gtk.Button cancel_button; public Queue<string> display_package_queue; string current_package_displayed; string current_launchable; string current_files; string current_build_files; GenericSet<string?> previous_to_install; GenericSet<string?> previous_to_remove; GenericSet<string?> previous_to_build; public TransactionGtk transaction; public Database database { get; construct; } LocalConfig local_config; bool important_details; bool transaction_running; bool sysupgrade_running; bool generate_mirrors_list; bool waiting; bool force_refresh; List<Package> repos_updates; List<AURPackage> aur_updates; List<Package> current_packages_list; unowned List<Package> current_packages_list_pos; List<AURPackage> current_aur_list; unowned List<AURPackage> current_aur_list_pos; uint search_entry_timeout_id; Gtk.ListBoxRow files_row; Gtk.ListBoxRow build_files_row; bool scroll_to_top; string current_filter; public ManagerWindow (Gtk.Application application, Database database) { Object (application: application, database: database); } construct { unowned string? use_csd = Environment.get_variable ("GTK_CSD"); if (use_csd == "0") { headerbar.show_close_button = false; } local_config = new LocalConfig ("%s/pamac/size".printf (Environment.get_user_config_dir ())); this.resize ((int) local_config.width, (int) local_config.height); if (local_config.maximized) { this.set_default_size ((int) local_config.width, (int) local_config.height); this.maximize (); } button_back.visible = false; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; details_button.sensitive = false; scroll_to_top = true; searchbar.connect_entry (search_entry); important_details = false; transaction_running = false; sysupgrade_running = false; generate_mirrors_list = false; updated_label.set_markup ("<big><b>%s</b></big>".printf (dgettext (null, "Your system is up-to-date"))); no_item_label.set_markup ("<big><b>%s</b></big>".printf (dgettext (null, "No package found"))); checking_label.set_markup ("<big><b>%s</b></big>".printf (dgettext (null, "Checking for Updates"))); // auto complete list packages_scrolledwindow.vadjustment.value_changed.connect (() => { double max_value = (packages_scrolledwindow.vadjustment.upper - packages_scrolledwindow.vadjustment.page_size) * 0.8; if (packages_scrolledwindow.vadjustment.value >= max_value) { complete_packages_list (); } }); packages_scrolledwindow.vadjustment.changed.connect (() => { while (need_more_packages ()) { complete_packages_list (); } }); aur_scrolledwindow.vadjustment.value_changed.connect (() => { double max_value = (aur_scrolledwindow.vadjustment.upper - aur_scrolledwindow.vadjustment.page_size) * 0.8; if (aur_scrolledwindow.vadjustment.value >= max_value) { complete_aur_list (); } }); aur_scrolledwindow.vadjustment.changed.connect (() => { while (need_more_aur ()) { complete_aur_list (); } }); // packages listbox functions packages_listbox.set_header_func (set_header_func); aur_listbox.set_header_func (set_header_func); // icons icon_theme = Gtk.IconTheme.get_default (); icon_theme.changed.connect (update_icons); update_icons (); // database database.get_updates_progress.connect (on_get_updates_progress); database.refreshed.connect (() => { scroll_to_top = false; refresh_packages_list (); }); create_all_listbox (); // transaction transaction = new TransactionGtk (database, this); transaction.start_waiting.connect (on_start_waiting); transaction.stop_waiting.connect (on_stop_waiting); transaction.start_preparing.connect (on_start_preparing); transaction.stop_preparing.connect (on_stop_preparing); transaction.start_downloading.connect (on_start_downloading); transaction.stop_downloading.connect (on_stop_downloading); transaction.start_building.connect (on_start_building); transaction.stop_building.connect (on_stop_building); transaction.important_details_outpout.connect (on_important_details_outpout); transaction.sysupgrade_finished.connect (on_transaction_finished); transaction.finished.connect (on_transaction_finished); transaction.write_pamac_config_finished.connect (on_write_pamac_config_finished); transaction.set_pkgreason_finished.connect (on_set_pkgreason_finished); transaction.start_generating_mirrors_list.connect (on_start_generating_mirrors_list); transaction.generate_mirrors_list_finished.connect (on_generate_mirrors_list_finished); transaction.transaction_sum_populated.connect (() => { // make buttons of pkgs in transaction unsensitive packages_listbox.foreach ((row) => { unowned PackageRow pamac_row = row as PackageRow; if (pamac_row == null) { return; } if (transaction.transaction_summary.contains (pamac_row.pkg.name)) { pamac_row.action_togglebutton.active = false; pamac_row.action_togglebutton.sensitive = false; pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); } }); aur_listbox.foreach ((row) => { unowned AURRow pamac_row = row as AURRow; if (pamac_row == null) { return; } if (transaction.transaction_summary.contains (pamac_row.aur_pkg.name)) { pamac_row.action_togglebutton.active = false; pamac_row.action_togglebutton.sensitive = false; pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); } }); }); // integrate progress box and term widget main_stack.add_named (transaction.details_window, "term"); transaction_infobox.pack_start (transaction.progress_box); // integrate build files notebook build_files_box.add (transaction.build_files_notebook); display_package_queue = new Queue<string> (); to_install = new GenericSet<string?> (str_hash, str_equal); to_remove = new GenericSet<string?> (str_hash, str_equal); to_load = new GenericSet<string?> (str_hash, str_equal); to_build = new GenericSet<string?> (str_hash, str_equal); previous_to_install = new GenericSet<string?> (str_hash, str_equal); previous_to_remove = new GenericSet<string?> (str_hash, str_equal); previous_to_build = new GenericSet<string?> (str_hash, str_equal); to_update = new GenericSet<string?> (str_hash, str_equal); temporary_ignorepkgs = new GenericSet<string?> (str_hash, str_equal); main_stack.notify["visible-child"].connect (on_main_stack_visible_child_changed); browse_stack.notify["visible-child"].connect (on_browse_stack_visible_child_changed); filters_stack.notify["visible-child"].connect (on_filters_stack_visible_child_changed); origin_stack.notify["visible-child"].connect (on_origin_stack_visible_child_changed); searchbar.notify["search-mode-enabled"].connect (on_search_mode_enabled); // enable "type to search" this.key_press_event.connect ((event) => { if (main_stack.visible_child_name == "browse" && (browse_stack.visible_child_name == "browse" || browse_stack.visible_child_name == "installed")) { return searchbar.handle_event (event); } return false; }); // create screenshots tmp dir string screenshots_tmp_dir = "/tmp/pamac-app-screenshots"; var file = GLib.File.new_for_path (screenshots_tmp_dir); if (!file.query_exists ()) { try { Process.spawn_command_line_sync ("mkdir -p %s".printf (screenshots_tmp_dir)); Process.spawn_command_line_sync ("chmod -R a+w %s".printf (screenshots_tmp_dir)); } catch (SpawnError e) { stderr.printf ("SpawnError: %s\n", e.message); } } } void set_header_func (Gtk.ListBoxRow row, Gtk.ListBoxRow? row_before) { row.set_header (new Gtk.Separator (Gtk.Orientation.HORIZONTAL)); } void update_icons () { icon_theme = Gtk.IconTheme.get_default (); try { package_icon = icon_theme.load_icon ("package-x-generic", 64, 0); } catch (GLib.Error e) { stderr.printf ("%s\n", e.message); } } [GtkCallback] bool on_ManagerWindow_delete_event () { if (transaction_running || sysupgrade_running || generate_mirrors_list) { // do not close window return true; } else { // save window size var local_conf = new HashTable<string,Variant> (str_hash, str_equal); if (this.is_maximized) { local_conf.insert ("maximized", new Variant.boolean (true)); } else { int width, height; this.get_size (out width, out height); local_conf.insert ("maximized", new Variant.boolean (false)); local_conf.insert ("width", new Variant.uint64 (width)); local_conf.insert ("height", new Variant.uint64 (height)); } local_config.write (local_conf); // close window return false; } } void on_write_pamac_config_finished (bool recurse, uint64 refresh_period, bool no_update_hide_icon, bool enable_aur) { support_aur (enable_aur); } void on_set_pkgreason_finished () { if (main_stack.visible_child_name == "details") { if (database.is_installed_pkg (current_package_displayed) || database.is_sync_pkg (current_package_displayed)) { display_package_properties (current_package_displayed); } else { display_aur_properties (current_package_displayed); } } } void support_aur (bool enable_aur) { unowned Gtk.ListBoxRow aur_row = search_listbox.get_row_at_index (2); if (enable_aur) { aur_row.visible = true; } else { aur_row.visible = false; unowned Gtk.ListBoxRow installed_row = search_listbox.get_row_at_index (0); installed_row.activatable = true; installed_row.selectable = true; installed_row.can_focus = true; installed_row.get_child ().sensitive = true; search_listbox.select_row (installed_row); on_search_listbox_row_activated (search_listbox.get_selected_row ()); unowned Gtk.ListBoxRow repos_row = search_listbox.get_row_at_index (1); repos_row.activatable = true; repos_row.selectable = true; repos_row.can_focus = true; repos_row.get_child ().sensitive = true; } } void hide_sidebar () { sidebar_revealer.set_reveal_child (false); } void show_sidebar () { sidebar_revealer.set_reveal_child (true); } void hide_transaction_infobox () { transaction_infobox_revealer.set_reveal_child (false); } void show_transaction_infobox () { transaction_infobox_revealer.set_reveal_child (true); } void set_pendings_operations () { if (!transaction_running && !generate_mirrors_list && !sysupgrade_running) { if (browse_stack.visible_child_name == "updates") { uint64 total_dsize = 0; foreach (unowned Package pkg in current_packages_list) { if (pkg.name in to_update) { total_dsize += pkg.download_size; } } if (total_dsize > 0) { transaction.progress_box.action_label.set_markup("<b>%s: %s</b>".printf (dgettext (null, "Total download size"), format_size (total_dsize))); } else { transaction.progress_box.action_label.label = ""; } if (!transaction_running && !generate_mirrors_list && !sysupgrade_running && (to_update.length > 0)) { apply_button.sensitive = true; } else { apply_button.sensitive = false; } cancel_button.sensitive = false; show_transaction_infobox (); } else { uint total_pending = to_install.length + to_remove.length + to_build.length; if (total_pending == 0) { if (browse_stack.visible_child_name != "pending") { active_pending_stack (false); } transaction.progress_box.action_label.label = ""; cancel_button.sensitive = false; apply_button.sensitive = false; if (important_details) { show_transaction_infobox (); } } else { active_pending_stack (true); string info = dngettext (null, "%u pending operation", "%u pending operations", total_pending).printf (total_pending); transaction.progress_box.action_label.label = info; cancel_button.sensitive = true; apply_button.sensitive = true; show_transaction_infobox (); } } } } void show_default_pkgs () { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); current_filter = "installed_apps"; database.get_installed_apps_async.begin ((obj, res) => { if (current_filter != "installed_apps") { return; } populate_packages_list (database.get_installed_apps_async.end (res)); }); } Gtk.ListBoxRow create_list_row (string str) { var label = new Gtk.Label (str); label.visible = true; label.margin = 12; label.xalign = 0; var row = new Gtk.ListBoxRow (); row.visible = true; row.add (label); return row; } int sort_list_row (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) { unowned Gtk.Label label1 = row1.get_child () as Gtk.Label; unowned Gtk.Label label2 = row2.get_child () as Gtk.Label; return strcmp (label1.label, label2.label); } void active_pending_stack (bool active) { pending_listbox.visible = active; } void create_all_listbox () { filters_listbox.add (create_list_row (dgettext (null, "Categories"))); filters_listbox.add (create_list_row (dgettext (null, "Groups"))); filters_listbox.add (create_list_row (dgettext (null, "Repositories"))); repos_names = database.get_repos_names (); foreach (unowned string repo in repos_names) { repos_listbox.add (create_list_row (repo)); } repos_listbox.select_row (repos_listbox.get_row_at_index (0)); foreach (unowned string group in database.get_groups_names ()) { groups_listbox.add (create_list_row (group)); } groups_listbox.set_sort_func (sort_list_row); groups_listbox.select_row (groups_listbox.get_row_at_index (0)); installed_listbox.add (create_list_row (dgettext (null, "Installed"))); installed_listbox.add (create_list_row (dgettext (null, "Explicitly installed"))); installed_listbox.add (create_list_row (dgettext (null, "Orphans"))); installed_listbox.add (create_list_row (dgettext (null, "Foreign"))); installed_listbox.select_row (installed_listbox.get_row_at_index (0)); categories_listbox.add (create_list_row (dgettext (null, "Accessories"))); categories_listbox.add (create_list_row (dgettext (null, "Audio & Video"))); categories_listbox.add (create_list_row (dgettext (null, "Development"))); categories_listbox.add (create_list_row (dgettext (null, "Education"))); categories_listbox.add (create_list_row (dgettext (null, "Games"))); categories_listbox.add (create_list_row (dgettext (null, "Graphics"))); categories_listbox.add (create_list_row (dgettext (null, "Internet"))); categories_listbox.add (create_list_row (dgettext (null, "Office"))); categories_listbox.add (create_list_row (dgettext (null, "Science"))); categories_listbox.add (create_list_row (dgettext (null, "Settings"))); categories_listbox.add (create_list_row (dgettext (null, "System Tools"))); categories_listbox.set_sort_func (sort_list_row); categories_listbox.select_row (categories_listbox.get_row_at_index (0)); updates_listbox.add (create_list_row (dgettext (null, "Repositories"))); updates_listbox.add (create_list_row (dgettext (null, "AUR"))); updates_listbox.select_row (updates_listbox.get_row_at_index (0)); pending_listbox.add (create_list_row (dgettext (null, "Repositories"))); pending_listbox.add (create_list_row (dgettext (null, "AUR"))); pending_listbox.select_row (pending_listbox.get_row_at_index (0)); active_pending_stack (false); search_listbox.add (create_list_row (dgettext (null, "Installed"))); search_listbox.add (create_list_row (dgettext (null, "Repositories"))); search_listbox.add (create_list_row (dgettext (null, "AUR"))); search_listbox.select_row (search_listbox.get_row_at_index (0)); if (database.config.enable_aur == false) { unowned Gtk.ListBoxRow row = search_listbox.get_row_at_index (2); row.visible = false; // related to #602 fix row.no_show_all = true; row.get_child ().no_show_all = true; // } properties_listbox.add (create_list_row (dgettext (null, "Details"))); properties_listbox.add (create_list_row (dgettext (null, "Dependencies"))); files_row = create_list_row (dgettext (null, "Files")); properties_listbox.add (files_row); build_files_row = create_list_row (dgettext (null, "Build files")); properties_listbox.add (build_files_row); properties_listbox.select_row (properties_listbox.get_row_at_index (0)); } void clear_packages_listbox () { packages_listbox.foreach (transaction.destroy_widget); } void clear_aur_listbox () { aur_listbox.foreach (transaction.destroy_widget); } void clear_lists () { to_install.remove_all (); to_remove.remove_all (); to_build.remove_all (); to_load.remove_all (); } void clear_previous_lists () { previous_to_install.remove_all (); previous_to_remove.remove_all (); previous_to_build.remove_all (); } void on_mark_explicit_button_clicked (Gtk.Button button) { transaction.start_set_pkgreason (current_package_displayed, 0); //Alpm.Package.Reason.EXPLICIT } Gtk.Widget populate_details_grid (string detail_type, string detail, Gtk.Widget? previous_widget) { var label = new Gtk.Label ("<b>%s:</b>".printf (detail_type)); label.use_markup = true; label.halign = Gtk.Align.START; label.valign = Gtk.Align.START; details_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); if (!transaction_running && !sysupgrade_running && detail_type == dgettext (null, "Install Reason") && detail == dgettext (null, "Installed as a dependency for another package")) { var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); box.homogeneous = false; var label2 = new Gtk.Label (detail); label2.halign = Gtk.Align.START; box.pack_start (label2, false); var mark_explicit_button = new Gtk.Button.with_label (dgettext (null, "Mark as explicitly installed")); mark_explicit_button.halign = Gtk.Align.START; mark_explicit_button.clicked.connect (on_mark_explicit_button_clicked); box.pack_start (mark_explicit_button, false); details_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); } else { var label2 = new Gtk.Label (detail); label2.use_markup = true; label2.halign = Gtk.Align.START; details_grid.attach_next_to (label2, label, Gtk.PositionType.RIGHT); } return label as Gtk.Widget; } string find_install_button_dep_name (Gtk.Button button) { string dep_name = ""; Gtk.Container container = button.get_parent (); container.foreach ((widget) => { if (widget.name == "GtkButton") { unowned Gtk.Button dep_button = widget as Gtk.Button; Package pkg = database.find_sync_satisfier (dep_button.label); if (pkg.name != "") { dep_name = pkg.name; } } }); return dep_name; } void on_install_dep_button_toggled (Gtk.ToggleButton button) { string dep_name = find_install_button_dep_name (button); if (button.active) { button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_install.add (dep_name); } else { button.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_install.remove (dep_name); } set_pendings_operations (); } Gtk.Widget populate_dep_grid (string dep_type, List<string> dep_list, Gtk.Widget? previous_widget, bool add_install_button = false) { var label = new Gtk.Label ("<b>%s:</b>".printf (dep_type)); label.use_markup = true; label.halign = Gtk.Align.START; label.valign = Gtk.Align.START; label.margin_top = 6; deps_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 3); box.hexpand = true; foreach (unowned string dep in dep_list) { if (add_install_button) { var box2 = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); box2.homogeneous = false; var dep_button = new Gtk.Button.with_label (dep); dep_button.relief = Gtk.ReliefStyle.NONE; dep_button.valign = Gtk.Align.CENTER; dep_button.clicked.connect (on_dep_button_clicked); box2.pack_start (dep_button, false); if (database.find_installed_satisfier (dep).name == "") { var install_dep_button = new Gtk.ToggleButton.with_label (dgettext (null, "Install")); install_dep_button.margin = 3; install_dep_button.toggled.connect (on_install_dep_button_toggled); box2.pack_end (install_dep_button, false); string dep_name = find_install_button_dep_name (install_dep_button); install_dep_button.active = (dep_name in to_install); } box.pack_start (box2); } else { var dep_button = new Gtk.Button.with_label (dep); dep_button.relief = Gtk.ReliefStyle.NONE; dep_button.halign = Gtk.Align.START; dep_button.valign = Gtk.Align.CENTER; dep_button.clicked.connect (on_dep_button_clicked); box.pack_start (dep_button, false); } } deps_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); return label as Gtk.Widget; } async Gdk.Pixbuf get_screenshot_pixbuf (string url) { var uri = File.new_for_uri (url); var cached_screenshot = File.new_for_path ("/tmp/pamac-app-screenshots/%s".printf (uri.get_basename ())); Gdk.Pixbuf pixbuf = null; if (cached_screenshot.query_exists ()) { try { pixbuf = new Gdk.Pixbuf.from_file (cached_screenshot.get_path ()); } catch (GLib.Error e) { stderr.printf ("%s: %s\n", url, e.message); } } else { // download screenshot var session = new Soup.Session (); var utsname = Posix.utsname(); session.user_agent = "pamac (%s %s)".printf (utsname.sysname, utsname.machine); try { var request = session.request (url); try { var inputstream = yield request.send_async (null); pixbuf = new Gdk.Pixbuf.from_stream (inputstream); // scale pixbux at a width of 600 pixels int width = pixbuf.get_width (); if (width > 600) { float ratio = (float) width / (float) pixbuf.get_height (); int new_height = (int) (600 / ratio); pixbuf = pixbuf.scale_simple (600, new_height, Gdk.InterpType.BILINEAR); } // save scaled image in tmp FileOutputStream os = cached_screenshot.append_to (FileCreateFlags.NONE); pixbuf.save_to_stream (os, "png"); } catch (GLib.Error e) { stderr.printf ("%s: %s\n", url, e.message); } } catch (GLib.Error e) { stderr.printf ("%s: %s\n", url, e.message); } } return pixbuf; } async void set_package_details (string pkgname, string app_name, bool sync_pkg) { PackageDetails details = database.get_pkg_details (pkgname, app_name, sync_pkg); // download screenshot app_screenshot.pixbuf = null; if (details.screenshot != "") { get_screenshot_pixbuf.begin (details.screenshot, (obj, res) => { var pixbuf = get_screenshot_pixbuf.end (res); app_screenshot.pixbuf = pixbuf; }); } // infos if (details.app_name == "") { name_label.set_markup ("<big><b>%s %s</b></big>".printf (details.name, details.version)); app_image.pixbuf = package_icon; } else { name_label.set_markup ("<big><b>%s (%s) %s</b></big>".printf (Markup.escape_text (details.app_name), details.name, details.version)); if (details.icon != "") { try { var pixbuf = new Gdk.Pixbuf.from_file (details.icon); app_image.pixbuf = pixbuf; } catch (GLib.Error e) { // some icons are not in the right repo string icon = details.icon; if ("extra" in details.icon) { icon = details.icon.replace ("extra", "community"); } else if ("community" in details.icon) { icon = details.icon.replace ("community", "extra"); } try { var pixbuf = new Gdk.Pixbuf.from_file (icon); app_image.pixbuf = pixbuf; } catch (GLib.Error e) { app_image.pixbuf = package_icon; stderr.printf ("%s: %s\n", details.icon, e.message); } } } else { app_image.pixbuf = package_icon; } } desc_label.set_text (details.desc); if (details.long_desc == "") { long_desc_label.visible = false; } else { long_desc_label.set_text (details.long_desc); long_desc_label.visible = true; } string escaped_url = Markup.escape_text (details.url); link_label.set_markup ("<a href=\"%s\">%s</a>".printf (escaped_url, escaped_url)); StringBuilder licenses = new StringBuilder (); licenses.append (dgettext (null, "Licenses")); licenses.append (":"); foreach (unowned string license in details.licenses) { licenses.append (" "); licenses.append (license); } licenses_label.set_text (licenses.str); if (details.installed_version != "") { if (details.launchable != "") { launch_button.visible = true; current_launchable = details.launchable; } else { launch_button.visible = false; } install_togglebutton.visible = false; build_togglebutton.visible = false; reset_files_button.visible = false; reinstall_togglebutton.visible = false; remove_togglebutton.visible = true; if (database.should_hold (pkgname)) { remove_togglebutton.sensitive = false; } else { remove_togglebutton.sensitive = true; remove_togglebutton.active = to_remove.contains (details.name); Package find_pkg = database.get_sync_pkg (details.name); if (find_pkg.name != "") { if (find_pkg.version == details.version) { reinstall_togglebutton.visible = true; reinstall_togglebutton.active = to_install.contains (details.name); } } else { AURPackage aur_pkg = yield database.get_aur_pkg (details.name); if (aur_pkg.name != "") { // always show reinstall button for VCS package if (aur_pkg.name.has_suffix ("-git") || aur_pkg.name.has_suffix ("-svn") || aur_pkg.name.has_suffix ("-bzr") || aur_pkg.name.has_suffix ("-hg") || aur_pkg.version == details.version) { build_togglebutton.visible = true; build_togglebutton.active = to_build.contains (details.name); } build_files_row.visible = true; string aur_url = "http://aur.archlinux.org/packages/" + details.name; link_label.set_markup ("<a href=\"%s\">%s</a>\n\n<a href=\"%s\">%s</a>".printf (escaped_url, escaped_url, aur_url, aur_url)); } } } } else { launch_button.visible = false; remove_togglebutton.visible = false; reinstall_togglebutton.visible = false; build_togglebutton.visible = false; reset_files_button.visible = false; install_togglebutton.visible = true; install_togglebutton.active = to_install.contains (details.name); } // details details_grid.foreach (transaction.destroy_widget); Gtk.Widget? previous_widget = null; if (details.repo != "") { previous_widget = populate_details_grid (dgettext (null, "Repository"), details.repo, previous_widget); } if (details.repo == dgettext (null, "AUR")) { AURPackageDetails aur_pkg_details = yield database.get_aur_pkg_details (details.name); if (aur_pkg_details.packagebase != details.name) { previous_widget = populate_details_grid (dgettext (null, "Package Base"), aur_pkg_details.packagebase, previous_widget); } if (aur_pkg_details.maintainer != "") { previous_widget = populate_details_grid (dgettext (null, "Maintainer"), aur_pkg_details.maintainer, previous_widget); } if (aur_pkg_details.firstsubmitted != 0) { var time = GLib.Time.local ((time_t) aur_pkg_details.firstsubmitted); previous_widget = populate_details_grid (dgettext (null, "First Submitted"), time.format ("%x"), previous_widget); } if (aur_pkg_details.lastmodified != 0) { var time = GLib.Time.local ((time_t) aur_pkg_details.lastmodified); previous_widget = populate_details_grid (dgettext (null, "Last Modified"), time.format ("%x"), previous_widget); } if (aur_pkg_details.numvotes != 0) { previous_widget = populate_details_grid (dgettext (null, "Votes"), aur_pkg_details.numvotes.to_string (), previous_widget); } if (aur_pkg_details.outofdate != 0) { var time = GLib.Time.local ((time_t) aur_pkg_details.outofdate); previous_widget = populate_details_grid (dgettext (null, "Out of Date"), time.format ("%x"), previous_widget); } } if (details.groups.length () > 0) { var label = new Gtk.Label ("<b>%s</b>".printf (dgettext (null, "Groups") + ":")); label.use_markup = true; label.halign = Gtk.Align.START; label.valign = Gtk.Align.START; details_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 6); foreach (unowned string name in details.groups) { var label2 = new Gtk.Label (name); label2.halign = Gtk.Align.START; box.pack_start (label2); } details_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); previous_widget = label as Gtk.Widget; } // make packager mail clickable string[] splitted = details.packager.split ("<", 2); string packager_name = splitted[0]; if (splitted.length > 1) { string packager_mail = splitted[1].split (">", 2)[0]; string packager_detail = "%s <a href=\"mailto:%s\">%s</a>".printf (packager_name, packager_mail, packager_mail); previous_widget = populate_details_grid (dgettext (null, "Packager"), packager_detail, previous_widget); } else { previous_widget = populate_details_grid (dgettext (null, "Packager"), details.packager, previous_widget); } var time = GLib.Time.local ((time_t) details.builddate); previous_widget = populate_details_grid (dgettext (null, "Build Date"), time.format ("%x"), previous_widget); if (details.installdate != 0) { time = GLib.Time.local ((time_t) details.installdate); previous_widget = populate_details_grid (dgettext (null, "Install Date"), time.format ("%x"), previous_widget); } if (details.reason != "") { previous_widget = populate_details_grid (dgettext (null, "Install Reason"), details.reason, previous_widget); } if (details.has_signature != "") { previous_widget = populate_details_grid (dgettext (null, "Signatures"), details.has_signature, previous_widget); } if (details.backups.length () > 0) { var label = new Gtk.Label ("<b>%s</b>".printf (dgettext (null, "Backup files") + ":")); label.use_markup = true; label.halign = Gtk.Align.START; label.valign = Gtk.Align.START; details_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); foreach (unowned string name in details.backups) { var label2 = new Gtk.Label (name); label2.halign = Gtk.Align.START; box.pack_start (label2); } details_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); } details_grid.show_all (); // deps deps_grid.foreach (transaction.destroy_widget); previous_widget = null; if (details.depends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Depends On"), details.depends, previous_widget); } if (details.optdepends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Optional Dependencies"), details.optdepends, previous_widget, true); } if (details.requiredby.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Required By"), details.requiredby, previous_widget); } if (details.optionalfor.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Optional For"), details.optionalfor, previous_widget); } if (details.provides.length () > 0) { var label = new Gtk.Label ("<b>%s</b>".printf (dgettext (null, "Provides") + ":")); label.use_markup = true; label.halign = Gtk.Align.START; label.valign = Gtk.Align.START; label.margin_top = 6; deps_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); box.margin = 3; foreach (unowned string name in details.provides) { var label2 = new Gtk.Label (name); label2.halign = Gtk.Align.START; label2.margin_start = 12; box.pack_start (label2); } deps_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); previous_widget = label as Gtk.Widget; } if (details.replaces.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Replaces"), details.replaces, previous_widget); } if (details.conflicts.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Conflicts With"), details.conflicts, previous_widget); } deps_grid.show_all (); // files // will be populated on properties_stack switch if (properties_stack.visible_child_name == "files") { properties_listbox.get_row_at_index (2).activate (); } } async void set_aur_details (string pkgname) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); details_grid.foreach (transaction.destroy_widget); deps_grid.foreach (transaction.destroy_widget); AURPackageDetails details = yield database.get_aur_pkg_details (pkgname); app_screenshot.pixbuf = null; launch_button.visible = false; remove_togglebutton.visible = false; reinstall_togglebutton.visible = false; install_togglebutton.visible = false; reset_files_button.visible = false; // infos name_label.set_markup ("<big><b>%s %s</b></big>".printf (details.name, details.version)); app_image.pixbuf = package_icon; desc_label.set_text (details.desc); long_desc_label.visible = false; string aur_url = "http://aur.archlinux.org/packages/" + details.name; string escaped_url = Markup.escape_text (details.url); link_label.set_markup ("<a href=\"%s\">%s</a>\n\n<a href=\"%s\">%s</a>".printf (escaped_url, escaped_url, aur_url, aur_url)); StringBuilder licenses = new StringBuilder (); licenses.append (dgettext (null, "Licenses")); licenses.append (":"); foreach (unowned string license in details.licenses) { licenses.append (" "); licenses.append (license); } licenses_label.set_text (licenses.str); build_togglebutton.visible = true; build_togglebutton.active = to_build.contains (details.name); if (database.is_installed_pkg (details.name)) { remove_togglebutton.visible = true; remove_togglebutton.active = to_remove.contains (details.name); } // details properties_listbox.visible = true; Gtk.Widget? previous_widget = null; if (details.packagebase != details.name) { previous_widget = populate_details_grid (dgettext (null, "Package Base"), details.packagebase, previous_widget); } if (details.maintainer != "") { previous_widget = populate_details_grid (dgettext (null, "Maintainer"), details.maintainer, previous_widget); } var time = GLib.Time.local ((time_t) details.firstsubmitted); previous_widget = populate_details_grid (dgettext (null, "First Submitted"), time.format ("%x"), previous_widget); time = GLib.Time.local ((time_t) details.lastmodified); previous_widget = populate_details_grid (dgettext (null, "Last Modified"), time.format ("%x"), previous_widget); previous_widget = populate_details_grid (dgettext (null, "Votes"), details.numvotes.to_string (), previous_widget); if (details.outofdate != 0) { time = GLib.Time.local ((time_t) details.outofdate); previous_widget = populate_details_grid (dgettext (null, "Out of Date"), time.format ("%x"), previous_widget); } details_grid.show_all (); // deps previous_widget = null; if (details.depends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Depends On"), details.depends, previous_widget); } if (details.makedepends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Make Dependencies"), details.makedepends, previous_widget); } if (details.checkdepends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Check Dependencies"), details.checkdepends, previous_widget); } if (details.optdepends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Optional Dependencies"), details.optdepends, previous_widget); } if (details.provides.length () > 0) { var label = new Gtk.Label ("<b>%s</b>".printf (dgettext (null, "Provides") + ":")); label.use_markup = true; label.halign = Gtk.Align.START; label.valign = Gtk.Align.START; label.margin_top = 6; deps_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); box.margin = 3; foreach (unowned string name in details.provides) { var label2 = new Gtk.Label (name); label2.halign = Gtk.Align.START; label2.margin_start = 12; box.pack_start (label2); } deps_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); previous_widget = label as Gtk.Widget; } if (details.replaces.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Replaces"), details.replaces, previous_widget); } if (details.conflicts.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Conflicts With"), details.conflicts, previous_widget); } deps_grid.show_all (); this.get_window ().set_cursor (null); // build files // will be populated on properties_stack switch if (properties_stack.visible_child_name == "build_files") { properties_listbox.get_row_at_index (3).activate (); } } [GtkCallback] void on_properties_listbox_row_activated (Gtk.ListBoxRow row) { int index = row.get_index (); switch (index) { case 0: // details reset_files_button.visible = false; properties_stack.visible_child_name = "details"; break; case 1: // deps reset_files_button.visible = false; properties_stack.visible_child_name = "deps"; break; case 2: // files reset_files_button.visible = false; if (current_files != current_package_displayed) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); database.get_pkg_files_async.begin (current_package_displayed, (obj, res) => { var files = database.get_pkg_files_async.end (res); StringBuilder text = new StringBuilder (); foreach (unowned string file in files) { if (text.len > 0) { text.append ("\n"); } text.append (file); } files_textview.buffer.set_text (text.str, (int) text.len); properties_stack.visible_child_name = "files"; this.get_window ().set_cursor (null); }); current_files = current_package_displayed; } else { properties_stack.visible_child_name = "files"; } break; case 3: // build files reset_files_button.visible = true; if (current_build_files != current_package_displayed) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); database.get_aur_pkg.begin (current_package_displayed, (obj, res) => { AURPackage pkg = database.get_aur_pkg.end (res); transaction.populate_build_files.begin (pkg.packagebase, true, false, () => { properties_stack.visible_child_name = "build_files"; }); this.get_window ().set_cursor (null); }); current_build_files = current_package_displayed; } else { properties_stack.visible_child_name = "build_files"; } break; default: break; } } [GtkCallback] void on_launch_button_clicked () { try { Process.spawn_command_line_sync ("gtk-launch %s".printf (current_launchable)); } catch (SpawnError e) { stderr.printf ("SpawnError: %s\n", e.message); } } [GtkCallback] void on_install_togglebutton_toggled () { if (install_togglebutton.active) { install_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_install.add (current_package_displayed); } else { install_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_install.remove (current_package_displayed); } set_pendings_operations (); } [GtkCallback] void on_build_togglebutton_toggled () { if (build_togglebutton.active) { build_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_build.add (current_package_displayed); if (properties_stack.visible_child_name == "build_files") { transaction.save_build_files.begin (current_package_displayed); } } else { build_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_build.remove (current_package_displayed); } set_pendings_operations (); } [GtkCallback] void on_reset_files_button_clicked () { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); database.get_aur_pkg.begin (current_package_displayed, (obj, res) => { AURPackage pkg = database.get_aur_pkg.end (res); transaction.populate_build_files.begin (pkg.packagebase, true, true); this.get_window ().set_cursor (null); }); } [GtkCallback] void on_remove_togglebutton_toggled () { if (remove_togglebutton.active) { reinstall_togglebutton.active = false; reinstall_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); remove_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); to_install.remove (current_package_displayed); to_remove.add (current_package_displayed); } else { remove_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); to_remove.remove (current_package_displayed); } set_pendings_operations (); } [GtkCallback] void on_reinstall_togglebutton_toggled () { if (reinstall_togglebutton.active) { remove_togglebutton.active = false; remove_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); reinstall_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_remove.remove (current_package_displayed); if (database.is_sync_pkg (current_package_displayed)) { to_install.add (current_package_displayed); } else { // availability in AUR was checked in set_package_details to_build.add (current_package_displayed); } } else { reinstall_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); to_install.remove (current_package_displayed); to_build.remove (current_package_displayed); } set_pendings_operations (); } void sort_packages_list () { int sort_index = sort_comboboxtext.active; switch (sort_index) { case 0: // relevance if (browse_stack.visible_child_name != "search") { current_packages_list.sort (sort_pkgs_by_relevance); } break; case 1: // name current_packages_list.sort (sort_pkgs_by_name); break; case 2: // date current_packages_list.sort (sort_pkgs_by_date); break; case 3: // repository current_packages_list.sort (sort_pkgs_by_repo); break; case 4: // size current_packages_list.sort (sort_pkgs_by_size); break; default: break; } } void populate_packages_list (owned List<Package> pkgs) { // populate listbox if (pkgs.length () == 0) { origin_stack.visible_child_name = "no_item"; this.get_window ().set_cursor (null); return; } else { packages_listbox.freeze_child_notify (); clear_packages_listbox (); packages_listbox.thaw_child_notify (); origin_stack.visible_child_name = "repos"; } current_packages_list = (owned) pkgs; sort_packages_list (); current_packages_list_pos = current_packages_list; do { complete_packages_list (); } while (need_more_packages ()); // scroll to top if (scroll_to_top) { packages_scrolledwindow.vadjustment.value = 0; } else { // don't scroll to top just once scroll_to_top = true; } this.get_window ().set_cursor (null); } bool need_more_packages () { if (current_packages_list_pos != null) { int natural_height; packages_listbox.get_preferred_height (null, out natural_height); if (packages_scrolledwindow.vadjustment.page_size > natural_height) { return true; } } return false; } void complete_packages_list () { if (current_packages_list_pos != null) { packages_listbox.freeze_child_notify (); uint i = 0; // display the next 20 packages while (i < 20) { var pkg = current_packages_list_pos.data; create_packagelist_row (pkg); i++; current_packages_list_pos = current_packages_list_pos.next; if (current_packages_list_pos == null) { // add an empty row to have an ending separator var row = new Gtk.ListBoxRow (); row.visible = true; packages_listbox.add (row); break; } } packages_listbox.thaw_child_notify (); } } void create_packagelist_row (Package pkg) { bool is_update = browse_stack.visible_child_name == "updates"; var row = new PackageRow (pkg); //populate info if (pkg.app_name == "") { row.name_label.set_markup ("<b>%s</b>".printf (pkg.name)); } else { row.name_label.set_markup ("<b>%s (%s)</b>".printf (Markup.escape_text (pkg.app_name), pkg.name)); } row.desc_label.label = pkg.desc; if (is_update) { var label = new Gtk.Label (pkg.version); label.visible = true; label.width_chars = 10; label.max_width_chars = 10; label.ellipsize = Pango.EllipsizeMode.END; label.xalign = 0; row.version_box.pack_start (label); label = new Gtk.Label ("(%s)".printf (pkg.installed_version)); label.visible = true; label.width_chars = 10; label.max_width_chars = 10; label.ellipsize = Pango.EllipsizeMode.END; label.xalign = 0; row.version_box.pack_start (label); row.size_label.label = pkg.download_size == 0 ? "" : GLib.format_size (pkg.download_size); } else { var label = new Gtk.Label (pkg.version); label.visible = true; label.width_chars = 10; label.max_width_chars = 10; label.ellipsize = Pango.EllipsizeMode.END; label.xalign = 0; row.version_box.pack_start (label); row.size_label.label = GLib.format_size (pkg.installed_size); } row.repo_label.label = pkg.repo; Gdk.Pixbuf pixbuf; if (pkg.icon != "") { try { pixbuf = new Gdk.Pixbuf.from_file_at_scale (pkg.icon, 32, 32, true); } catch (GLib.Error e) { // some icons are not in the right repo string icon = pkg.icon; if ("extra" in pkg.icon) { icon = pkg.icon.replace ("extra", "community"); } else if ("community" in pkg.icon) { icon = pkg.icon.replace ("community", "extra"); } try { pixbuf = new Gdk.Pixbuf.from_file_at_scale (icon, 32, 32, true); } catch (GLib.Error e) { pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); stderr.printf ("%s: %s\n", pkg.icon, e.message); } } } else { pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); } row.app_icon.pixbuf = pixbuf; row.details_button.clicked.connect (() => { on_packages_listbox_row_activated (row); }); if (transaction.transaction_summary.contains (pkg.name)) { row.action_togglebutton.sensitive = false; } if (pkg.installed_version == "") { row.action_togglebutton.label = dgettext (null, "Install"); if (pkg.name in to_install) { row.action_togglebutton.active = true; row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } row.action_togglebutton.toggled.connect ((button) => { if (button.active) { to_install.add (pkg.name); } else { to_install.remove (pkg.name); } refresh_listbox_buttons (); set_pendings_operations (); }); } else if (is_update) { row.action_togglebutton.label = dgettext (null, "Upgrade"); if (!(pkg.name in temporary_ignorepkgs)) { row.action_togglebutton.active = true; row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } row.action_togglebutton.toggled.connect ((button) => { if (button.active) { to_update.add (pkg.name); temporary_ignorepkgs.remove (pkg.name); } else { to_update.remove (pkg.name); temporary_ignorepkgs.add (pkg.name); } refresh_listbox_buttons (); set_pendings_operations (); }); } else { row.action_togglebutton.label = dgettext (null, "Remove"); if (database.should_hold (pkg.name)) { row.action_togglebutton.sensitive = false; } else if (pkg.name in to_remove) { row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); row.action_togglebutton.active = true; } row.action_togglebutton.toggled.connect ((button) => { if (button.active) { to_install.remove (pkg.name); to_remove.add (pkg.name); } else { to_remove.remove (pkg.name); } refresh_listbox_buttons (); set_pendings_operations (); }); } // insert packages_listbox.add (row); } void refresh_listbox_buttons () { packages_listbox.foreach ((row) => { unowned PackageRow pamac_row = row as PackageRow; if (pamac_row == null) { return; } unowned string pkgname = pamac_row.pkg.name; if (!database.should_hold (pkgname)) { pamac_row.action_togglebutton.sensitive = true; } if (pkgname in to_install) { pamac_row.action_togglebutton.active = true; pamac_row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } else if (pkgname in to_remove) { pamac_row.action_togglebutton.active = true; pamac_row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); } else if (pkgname in to_update) { pamac_row.action_togglebutton.active = true; pamac_row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } else if (pkgname in temporary_ignorepkgs) { pamac_row.action_togglebutton.active = false; pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } else { pamac_row.action_togglebutton.active = false; pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); } }); aur_listbox.foreach ((row) => { unowned AURRow pamac_row = row as AURRow; if (pamac_row == null) { return; } unowned string pkgname = pamac_row.aur_pkg.name; pamac_row.action_togglebutton.sensitive = true; if (pkgname in to_build) { pamac_row.action_togglebutton.active = true; pamac_row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } else if (pkgname in to_update) { pamac_row.action_togglebutton.active = true; pamac_row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } else if (pkgname in temporary_ignorepkgs) { pamac_row.action_togglebutton.active = false; pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } else { pamac_row.action_togglebutton.active = false; pamac_row.action_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } }); } void sort_aur_list () { int sort_index = sort_comboboxtext.active; switch (sort_index) { case 0: // relevance current_aur_list.sort (sort_aur_by_relevance); break; case 1: // name current_aur_list.sort (sort_aur_by_name); break; case 2: // date current_aur_list.sort (sort_aur_by_date); break; default: break; } } async void populate_aur_list (owned List<AURPackage> pkgs) { // populate listbox if (pkgs.length () == 0) { origin_stack.visible_child_name = "no_item"; this.get_window ().set_cursor (null); return; } else { aur_listbox.freeze_child_notify (); clear_aur_listbox (); aur_listbox.thaw_child_notify (); origin_stack.visible_child_name = "aur"; } current_aur_list = (owned) pkgs; sort_aur_list (); current_aur_list_pos = current_aur_list; do { complete_aur_list (); } while (need_more_aur ()); // scroll to top if (scroll_to_top) { aur_scrolledwindow.vadjustment.value = 0; } else { // don't scroll to top just once scroll_to_top = true; } this.get_window ().set_cursor (null); // get aur details to save time string[] pkgnames = {}; foreach (unowned AURPackage pkg in current_aur_list) { pkgnames += pkg.name; } yield database.get_aur_pkgs_details (pkgnames); } bool need_more_aur () { if (current_aur_list_pos != null) { int natural_height; aur_listbox.get_preferred_height (null, out natural_height); if (aur_scrolledwindow.vadjustment.page_size > natural_height) { return true; } } return false; } void complete_aur_list () { if (current_aur_list_pos != null) { aur_listbox.freeze_child_notify (); uint i = 0; // display the next 20 packages while (i < 20) { var pkg = current_aur_list_pos.data; create_aurlist_row (pkg); i++; current_aur_list_pos = current_aur_list_pos.next; if (current_aur_list_pos == null) { // add an empty row to have an ending separator var row = new Gtk.ListBoxRow (); row.visible = true; aur_listbox.add (row); break; } } aur_listbox.thaw_child_notify (); } } void create_aurlist_row (AURPackage aur_pkg) { bool is_update = browse_stack.visible_child_name == "updates"; var row = new AURRow (aur_pkg); //populate info row.name_label.set_markup ("<b>%s</b>".printf (aur_pkg.name)); if (is_update) { row.action_togglebutton.label = dgettext (null, "Upgrade"); var label = new Gtk.Label (aur_pkg.version); label.visible = true; label.width_chars = 10; label.max_width_chars = 10; label.ellipsize = Pango.EllipsizeMode.END; label.xalign = 0; row.version_box.pack_start (label); label = new Gtk.Label ("(%s)".printf (aur_pkg.installed_version)); label.visible = true; label.width_chars = 10; label.max_width_chars = 10; label.ellipsize = Pango.EllipsizeMode.END; label.xalign = 0; row.version_box.pack_start (label); } else { var label = new Gtk.Label (aur_pkg.version); label.visible = true; label.width_chars = 10; label.max_width_chars = 10; label.ellipsize = Pango.EllipsizeMode.END; label.xalign = 0; row.version_box.pack_start (label); } row.desc_label.label = aur_pkg.desc; row.app_icon.pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); row.details_button.clicked.connect (() => { on_aur_listbox_row_activated (row); }); if (is_update) { if (!(aur_pkg.name in temporary_ignorepkgs)) { row.action_togglebutton.active = true; row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } row.action_togglebutton.toggled.connect ((button) => { if (button.active) { to_update.add (aur_pkg.name); temporary_ignorepkgs.remove (aur_pkg.name); } else { to_update.remove (aur_pkg.name); temporary_ignorepkgs.add (aur_pkg.name); } refresh_listbox_buttons (); set_pendings_operations (); }); } else { if (aur_pkg.name in to_build) { row.action_togglebutton.active = true; row.action_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } row.action_togglebutton.toggled.connect ((button) => { if (button.active) { to_build.add (aur_pkg.name); } else { to_build.remove (aur_pkg.name); } refresh_listbox_buttons (); set_pendings_operations (); }); } // insert aur_listbox.add (row); } public void refresh_packages_list () { button_back.visible = (main_stack.visible_child_name != "browse" || (browse_stack.visible_child_name == "browse" && filters_stack.visible_child_name != "filters")); if (browse_stack.visible_child_name == "browse") { show_sidebar (); search_button.visible = true; switch (filters_stack.visible_child_name) { case "filters": show_default_pkgs (); header_filter_label.label = ""; search_button.active = false; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; set_pendings_operations (); break; case "categories": on_categories_listbox_row_activated (categories_listbox.get_selected_row ()); header_filter_label.set_markup ("<b>%s</b>".printf (dgettext (null, "Categories"))); search_button.active = false; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; set_pendings_operations (); break; case "groups": on_groups_listbox_row_activated (groups_listbox.get_selected_row ()); header_filter_label.set_markup ("<b>%s</b>".printf (dgettext (null, "Groups"))); search_button.active = false; ignore_all_button.visible = false; set_pendings_operations (); break; case "repos": on_repos_listbox_row_activated (repos_listbox.get_selected_row ()); header_filter_label.set_markup ("<b>%s</b>".printf (dgettext (null, "Repositories"))); search_button.active = false; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; set_pendings_operations (); break; default: break; } } else if (browse_stack.visible_child_name == "installed") { on_installed_listbox_row_activated (installed_listbox.get_selected_row ()); show_sidebar (); header_filter_label.label = ""; search_button.active = false; search_button.visible = true; install_all_button.visible = false; ignore_all_button.visible = false; set_pendings_operations (); } else if (browse_stack.visible_child_name == "updates") { database.get_updates.begin (on_get_updates_finished); this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); hide_sidebar (); origin_stack.visible_child_name = "checking"; header_filter_label.label = ""; search_button.active = false; search_button.visible = false; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; apply_button.sensitive = false; } else if (browse_stack.visible_child_name == "pending") { on_pending_listbox_row_activated (pending_listbox.get_selected_row ()); if (to_build.length == 0) { hide_sidebar (); } header_filter_label.label = ""; search_button.active = false; search_button.visible = false; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; } else if (browse_stack.visible_child_name == "search") { if (search_string != null) { // select last search_string bool found = false; search_comboboxtext.get_model ().foreach ((model, path, iter) => { string line; model.get (iter, 0, out line); if (line == search_string) { found = true; // we select the iter in search list // it will populate the packages list with the comboboxtext changed signal search_comboboxtext.set_active_iter (null); search_comboboxtext.set_active_iter (iter); } return found; }); if (!searchbar.search_mode_enabled) { searchbar.search_mode_enabled = true; } } header_filter_label.label = ""; remove_all_button.visible = false; install_all_button.visible = false; ignore_all_button.visible = false; set_pendings_operations (); } } public void display_package_properties (string pkgname, string app_name = "", bool sync_pkg = false) { current_package_displayed = pkgname; // select details if build files was selected if (properties_listbox.get_selected_row ().get_index () == 3) { properties_listbox.get_row_at_index (0).activate (); } files_row.visible = true; build_files_row.visible = false; set_package_details.begin (current_package_displayed, app_name, sync_pkg); } void display_aur_properties (string pkgname) { current_package_displayed = pkgname; // select details if files was selected if (properties_listbox.get_selected_row ().get_index () == 2) { properties_listbox.get_row_at_index (0).activate (); } files_row.visible = false; build_files_row.visible = true; set_aur_details.begin (current_package_displayed); } [GtkCallback] void on_packages_listbox_row_activated (Gtk.ListBoxRow row) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); main_stack.visible_child_name = "details"; bool sync_pkg = browse_stack.visible_child_name == "updates"; unowned PackageRow pamac_row = row as PackageRow; display_package_properties (pamac_row.pkg.name, pamac_row.pkg.app_name, sync_pkg); this.get_window ().set_cursor (null); } void on_dep_button_clicked (Gtk.Button button) { bool sync_pkg = false; if (browse_stack.visible_child_name == "updates") { sync_pkg = true; } if (display_package_queue.find_custom (current_package_displayed, strcmp) == null) { display_package_queue.push_tail (current_package_displayed); } string depstring = button.label; var pkg = database.find_installed_satisfier (depstring); if (pkg.name != "") { display_package_properties (pkg.name, "", sync_pkg); } else { pkg = database.find_sync_satisfier (depstring); if (pkg.name != "") { display_package_properties (pkg.name, "", sync_pkg); } else { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); string dep_name = database.get_alpm_dep_name (depstring); database.get_aur_pkg.begin (dep_name, (obj, res) => { this.get_window ().set_cursor (null); if (database.get_aur_pkg.end (res).name != "") { display_aur_properties (dep_name); } }); } } } [GtkCallback] void on_aur_listbox_row_activated (Gtk.ListBoxRow row) { unowned AURRow pamac_row = row as AURRow; if (browse_stack.visible_child_name == "updates") { display_aur_properties (pamac_row.aur_pkg.name); } else if (pamac_row.aur_pkg.installed_version != "") { display_package_properties (pamac_row.aur_pkg.name); } else { display_aur_properties (pamac_row.aur_pkg.name); } main_stack.visible_child_name = "details"; } [GtkCallback] public void on_button_back_clicked () { switch (main_stack.visible_child_name) { case "browse": filters_stack.visible_child_name = "filters"; search_entry.set_text (""); break; case "details": bool sync_pkg = false; if (browse_stack.visible_child_name == "updates") { sync_pkg = true; } string? pkgname = display_package_queue.pop_tail (); if (pkgname != null) { if (database.is_installed_pkg (pkgname) || database.is_sync_pkg (pkgname)) { display_package_properties (pkgname, "", sync_pkg); } else { database.get_aur_pkg.begin (pkgname, (obj, res) => { if (database.get_aur_pkg.end (res).name != "") { display_aur_properties (pkgname); } else { var pkg = database.find_installed_satisfier (pkgname); if (pkg.name == "") { pkg = database.find_sync_satisfier (pkgname); } if (pkg.name != "") { display_package_properties (pkgname, "", sync_pkg); } } }); } } else { main_stack.visible_child_name = "browse"; } break; case "term": main_stack.visible_child_name = "browse"; break; default: break; } } [GtkCallback] void on_updates_listbox_row_activated (Gtk.ListBoxRow row) { int index = row.get_index (); switch (index) { case 0: // repos this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); row.activatable = true; row.selectable = true; row.can_focus = true; row.get_child ().sensitive = true; ignore_all_button.visible = false; var pkgs = new List<Package> (); foreach (unowned Package pkg in repos_updates) { pkgs.append (pkg); } populate_packages_list ((owned) pkgs); break; case 1: // aur this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); var pkgs = new List<AURPackage> (); foreach (unowned AURPackage pkg in aur_updates) { pkgs.append (pkg); } populate_aur_list.begin ((owned) pkgs); if (aur_updates.length () > 0) { ignore_all_button.visible = true; } unowned Gtk.ListBoxRow repo_row = updates_listbox.get_row_at_index (0); if (repos_updates.length () > 0) { repo_row.activatable = true; repo_row.selectable = true; repo_row.can_focus = true; repo_row.get_child ().sensitive = true; } else { repo_row.activatable = false; repo_row.selectable = false; repo_row.has_focus = false; repo_row.can_focus = false; repo_row.get_child ().sensitive = false; } break; default: break; } } [GtkCallback] void on_pending_listbox_row_activated (Gtk.ListBoxRow row) { int index = row.get_index (); switch (index) { case 0: // repos if ((to_install.length + to_remove.length) > 0) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); row.activatable = true; row.selectable = true; row.can_focus = true; row.get_child ().sensitive = true; var pkgs = new List<Package> (); foreach (unowned string pkgname in to_install) { var pkg = database.get_installed_pkg (pkgname); if (pkg.name == "") { pkg = database.get_sync_pkg (pkgname); } if (pkg.name != "") { pkgs.append (pkg); } } foreach (unowned string pkgname in to_remove) { var pkg = database.get_installed_pkg (pkgname); if (pkg.name != "") { pkgs.append (pkg); } } populate_packages_list ((owned) pkgs); } unowned Gtk.ListBoxRow aur_row = pending_listbox.get_row_at_index (1); if (to_build.length > 0) { aur_row.activatable = true; aur_row.selectable = true; aur_row.can_focus = true; aur_row.get_child ().sensitive = true; if ((to_install.length + to_remove.length) == 0) { row.activatable = false; row.selectable = false; row.has_focus = false; row.can_focus = false; row.get_child ().sensitive = false; pending_listbox.select_row (aur_row); on_pending_listbox_row_activated (pending_listbox.get_selected_row ()); } } else { aur_row.activatable = false; aur_row.selectable = false; aur_row.has_focus = false; aur_row.can_focus = false; aur_row.get_child ().sensitive = false; } break; case 1: // aur if (to_build.length > 0) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); row.activatable = true; row.selectable = true; row.can_focus = true; row.get_child ().sensitive = true; populate_pendings_aur_pkgs.begin (); } unowned Gtk.ListBoxRow repo_row = pending_listbox.get_row_at_index (0); if ((to_install.length + to_remove.length) > 0) { repo_row.activatable = true; repo_row.selectable = true; repo_row.can_focus = true; repo_row.get_child ().sensitive = true; if (to_build.length == 0) { row.activatable = false; row.selectable = false; row.has_focus = false; row.can_focus = false; row.get_child ().sensitive = false; pending_listbox.select_row (repo_row); on_pending_listbox_row_activated (pending_listbox.get_selected_row ()); } } else { repo_row.activatable = false; repo_row.selectable = false; repo_row.has_focus = false; repo_row.can_focus = false; repo_row.get_child ().sensitive = false; } break; default: break; } } async void populate_pendings_aur_pkgs () { var aur_pkgs = new List<AURPackage> (); string[] to_build_array = {}; foreach (unowned string name in to_build) { to_build_array += name; } var table = yield database.get_aur_pkgs (to_build_array); foreach (unowned AURPackage aur_pkg in table.get_values ()) { if (aur_pkg.name != "") { aur_pkgs.append (aur_pkg); } } populate_aur_list.begin ((owned) aur_pkgs); } [GtkCallback] void on_search_listbox_row_activated (Gtk.ListBoxRow row) { int index = row.get_index (); switch (index) { case 0: // installed search_entry.grab_focus_without_selecting (); search_entry.set_position (-1); if (search_string == null) { return; } this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); current_filter = "search_installed_pkgs_%s".printf (search_string); database.search_installed_pkgs_async.begin (search_string, (obj, res) => { if (current_filter != "search_installed_pkgs_%s".printf (search_string)) { return; } var pkgs = database.search_installed_pkgs_async.end (res); if (pkgs.length () == 0) { database.search_repos_pkgs_async.begin (search_string, (obj, res) => { if (database.search_repos_pkgs_async.end (res).length () > 0) { row.activatable = false; row.selectable = false; row.has_focus = false; row.can_focus = false; row.get_child ().sensitive = false; unowned Gtk.ListBoxRow repos_row = search_listbox.get_row_at_index (1); repos_row.activatable = true; repos_row.selectable = true; repos_row.can_focus = true; repos_row.get_child ().sensitive = true; search_listbox.select_row (repos_row); on_search_listbox_row_activated (search_listbox.get_selected_row ()); } else if (database.config.enable_aur) { database.search_in_aur.begin (search_string, (obj, res) => { if (database.search_in_aur.end (res).length () > 0) { row.activatable = false; row.selectable = false; row.has_focus = false; row.can_focus = false; row.get_child ().sensitive = false; unowned Gtk.ListBoxRow repos_row = search_listbox.get_row_at_index (1); repos_row.activatable = false; repos_row.selectable = false; repos_row.has_focus = false; repos_row.can_focus = false; repos_row.get_child ().sensitive = false; unowned Gtk.ListBoxRow aur_row = search_listbox.get_row_at_index (2); aur_row.activatable = true; aur_row.selectable = true; aur_row.can_focus = true; aur_row.get_child ().sensitive = true; search_listbox.select_row (aur_row); on_search_listbox_row_activated (search_listbox.get_selected_row ()); } else { populate_packages_list ((owned) pkgs); } }); } else { populate_packages_list ((owned) pkgs); } }); } else { populate_packages_list ((owned) pkgs); database.search_repos_pkgs_async.begin (search_string, (obj, res) => { unowned Gtk.ListBoxRow repos_row = search_listbox.get_row_at_index (1); if (database.search_repos_pkgs_async.end (res).length () > 0) { repos_row.activatable = true; repos_row.selectable = true; repos_row.can_focus = true; repos_row.get_child ().sensitive = true; } else { repos_row.activatable = false; repos_row.selectable = false; repos_row.has_focus = false; repos_row.can_focus = false; repos_row.get_child ().sensitive = false; } }); } }); break; case 1: // repos search_entry.grab_focus_without_selecting (); search_entry.set_position (-1); if (search_string == null) { return; } this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); current_filter = "search_repos_pkgs_%s".printf (search_string); database.search_repos_pkgs_async.begin (search_string, (obj, res) => { if (current_filter != "search_repos_pkgs_%s".printf (search_string)) { return; } var pkgs = database.search_repos_pkgs_async.end (res); if (pkgs.length () == 0) { database.search_installed_pkgs_async.begin (search_string, (obj, res) => { if (database.search_installed_pkgs_async.end (res).length () > 0) { row.activatable = false; row.selectable = false; row.has_focus = false; row.can_focus = false; row.get_child ().sensitive = false; unowned Gtk.ListBoxRow installed_row = search_listbox.get_row_at_index (0); installed_row.activatable = true; installed_row.selectable = true; installed_row.can_focus = true; installed_row.get_child ().sensitive = true; search_listbox.select_row (installed_row); on_search_listbox_row_activated (search_listbox.get_selected_row ()); } else if (database.config.enable_aur) { database.search_in_aur.begin (search_string, (obj, res) => { if (database.search_in_aur.end (res).length () > 0) { row.activatable = false; row.selectable = false; row.has_focus = false; row.can_focus = false; row.get_child ().sensitive = false; unowned Gtk.ListBoxRow installed_row = search_listbox.get_row_at_index (0); installed_row.activatable = false; installed_row.selectable = false; installed_row.has_focus = false; installed_row.can_focus = false; installed_row.get_child ().sensitive = false; unowned Gtk.ListBoxRow aur_row = search_listbox.get_row_at_index (2); aur_row.activatable = true; aur_row.selectable = true; aur_row.can_focus = true; aur_row.get_child ().sensitive = true; search_listbox.select_row (aur_row); on_search_listbox_row_activated (search_listbox.get_selected_row ()); } else { populate_packages_list ((owned) pkgs); } }); } else { populate_packages_list ((owned) pkgs); } }); } else { populate_packages_list ((owned) pkgs); database.search_installed_pkgs_async.begin (search_string, (obj, res) => { unowned Gtk.ListBoxRow installed_row = search_listbox.get_row_at_index (0); if (database.search_installed_pkgs_async.end (res).length () > 0) { installed_row.activatable = true; installed_row.selectable = true; installed_row.can_focus = true; installed_row.get_child ().sensitive = true; } else { installed_row.activatable = false; installed_row.selectable = false; installed_row.has_focus = false; installed_row.can_focus = false; installed_row.get_child ().sensitive = false; } }); } }); break; case 2: // aur search_entry.grab_focus_without_selecting (); search_entry.set_position (-1); if (search_string == null) { origin_stack.visible_child_name = "no_item"; return; } this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); current_filter = "search_in_aur"; database.search_in_aur.begin (search_string, (obj, res) => { if (current_filter != "search_in_aur") { return; } populate_aur_list.begin (database.search_in_aur.end (res)); }); database.search_installed_pkgs_async.begin (search_string, (obj, res) => { unowned Gtk.ListBoxRow installed_row = search_listbox.get_row_at_index (0); if (database.search_installed_pkgs_async.end (res).length () > 0 ) { installed_row.activatable = true; installed_row.selectable = true; installed_row.can_focus = true; installed_row.get_child ().sensitive = true; } else { installed_row.activatable = false; installed_row.selectable = false; installed_row.has_focus = false; installed_row.can_focus = false; installed_row.get_child ().sensitive = false; } }); database.search_repos_pkgs_async.begin (search_string, (obj, res) => { unowned Gtk.ListBoxRow repos_row = search_listbox.get_row_at_index (1); if (database.search_repos_pkgs_async.end (res).length () > 0 ) { repos_row.activatable = true; repos_row.selectable = true; repos_row.can_focus = true; repos_row.get_child ().sensitive = true; } else { repos_row.activatable = false; repos_row.selectable = false; repos_row.has_focus = false; repos_row.can_focus = false; repos_row.get_child ().sensitive = false; } }); break; default: break; } } [GtkCallback] void on_remove_all_button_clicked () { foreach (unowned Package pkg in current_packages_list) { if (!transaction.transaction_summary.contains (pkg.name) && pkg.installed_version != "") { to_install.remove (pkg.name); to_remove.add (pkg.name); } } refresh_listbox_buttons (); set_pendings_operations (); } [GtkCallback] void on_install_all_button_clicked () { foreach (unowned Package pkg in current_packages_list) { if (!transaction.transaction_summary.contains (pkg.name) && pkg.installed_version == "") { to_install.add (pkg.name); } } refresh_listbox_buttons (); set_pendings_operations (); } [GtkCallback] void on_ignore_all_button_clicked () { foreach (unowned AURPackage aur_pkg in current_aur_list) { to_update.remove (aur_pkg.name); temporary_ignorepkgs.add (aur_pkg.name); } refresh_listbox_buttons (); set_pendings_operations (); } void on_search_mode_enabled () { if (searchbar.search_mode_enabled) { search_button.active = true; } } [GtkCallback] void on_search_button_toggled () { if (search_button.active) { searchbar.search_mode_enabled = true; } else { searchbar.search_mode_enabled = false; } // fix #602 install_all_button.no_show_all = true; remove_all_button.no_show_all = true; ignore_all_button.no_show_all = true; browse_box.show_all (); // } bool search_entry_timeout_callback () { // add search string in search_list if needed string tmp_search_string = search_comboboxtext.get_active_text ().strip (); if (tmp_search_string == "") { search_entry_timeout_id = 0; return false; } bool found = false; // check if search string exists in search list search_comboboxtext.get_model ().foreach ((model, path, iter) => { string line; model.get (iter, 0, out line); if (line == tmp_search_string) { found = true; // we select the iter in search list // it will populate the packages list with the comboboxtext changed signal search_comboboxtext.set_active_iter (iter); } return found; }); if (!found) { Gtk.TreeIter iter; unowned Gtk.ListStore store = search_comboboxtext.get_model () as Gtk.ListStore; store.insert_with_values (out iter, -1, 0, tmp_search_string); // we select the iter in search list // it will populate the packages list with the comboboxtext changed signal search_comboboxtext.set_active_iter (iter); } search_entry_timeout_id = 0; return false; } [GtkCallback] void on_search_comboboxtext_changed () { if (search_comboboxtext.get_active () == -1) { // entry was edited if (search_comboboxtext.get_active_text ().strip () != "") { if (search_entry_timeout_id != 0) { Source.remove (search_entry_timeout_id); } search_entry_timeout_id = Timeout.add (1000, search_entry_timeout_callback); } } else { // a history line was choosen this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); search_string = search_comboboxtext.get_active_text ().strip (); if (browse_stack.visible_child_name != "search") { // this function will be recalled when refresh_packages_list browse_stack.visible_child_name = "search"; return; } on_search_listbox_row_activated (search_listbox.get_selected_row ()); } } [GtkCallback] void on_search_entry_icon_press (Gtk.EntryIconPosition pos, Gdk.Event event) { if (pos == Gtk.EntryIconPosition.SECONDARY) { search_entry.set_text (""); } } [GtkCallback] void on_sort_comboboxtext_changed () { refresh_packages_list (); } [GtkCallback] void on_filters_listbox_row_activated (Gtk.ListBoxRow row) { int index = row.get_index (); switch (index) { case 0: // categories filters_stack.visible_child_name = "categories"; break; case 1: // groups filters_stack.visible_child_name = "groups"; break; case 2: // repos filters_stack.visible_child_name = "repos"; break; default: break; } } [GtkCallback] void on_categories_listbox_row_activated (Gtk.ListBoxRow row) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); unowned Gtk.Label label = row.get_child () as Gtk.Label; string matching_cat = ""; unowned string category = label.label; if (category == dgettext (null, "Accessories")) { matching_cat = "Utility"; } else if (category == dgettext (null, "Audio & Video")) { matching_cat = "AudioVideo"; } else if (category == dgettext (null, "Development")) { matching_cat = "Development"; } else if (category == dgettext (null, "Education")) { matching_cat = "Education"; } else if (category == dgettext (null, "Games")) { matching_cat = "Game"; } else if (category == dgettext (null, "Graphics")) { matching_cat = "Graphics"; } else if (category == dgettext (null, "Internet")) { matching_cat = "Network"; } else if (category == dgettext (null, "Office")) { matching_cat = "Office"; } else if (category == dgettext (null, "Science")) { matching_cat = "Science"; } else if (category == dgettext (null, "Settings")) { matching_cat = "Settings"; } else if (category == dgettext (null, "System Tools")) { matching_cat = "System"; } Timeout.add (200, () => { current_filter = "category_pkgs_%s".printf (matching_cat); database.get_category_pkgs_async.begin (matching_cat, (obj, res) => { if (current_filter != "category_pkgs_%s".printf (matching_cat)) { return; } populate_packages_list (database.get_category_pkgs_async.end (res)); }); return false; }); } [GtkCallback] void on_groups_listbox_row_activated (Gtk.ListBoxRow row) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); unowned Gtk.Label label = row.get_child () as Gtk.Label; unowned string group_name = label.label; Timeout.add (200, () => { current_filter = "group_pkgs_%s".printf (group_name); database.get_group_pkgs_async.begin (group_name, (obj, res) => { if (current_filter != "group_pkgs_%s".printf (group_name)) { return; } var pkgs = database.get_group_pkgs_async.end (res); bool found = false; foreach (unowned Package pkg in pkgs) { if (pkg.installed_version == "") { found = true; break; } } install_all_button.visible = found; found = false; foreach (unowned Package pkg in pkgs) { if (pkg.installed_version != "") { found = true; break; } } remove_all_button.visible = found; populate_packages_list ((owned) pkgs); }); return false; }); } [GtkCallback] void on_installed_listbox_row_activated (Gtk.ListBoxRow row) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); int index = row.get_index (); switch (index) { case 0: // Installed Timeout.add (200, () => { current_filter = "installed_pkgs"; database.get_installed_pkgs_async.begin ((obj, res) => { if (current_filter != "installed_pkgs") { return; } remove_all_button.visible = false; populate_packages_list (database.get_installed_pkgs_async.end (res)); }); return false; }); break; case 1: // Explicitly installed Timeout.add (200, () => { current_filter = "explicitly_installed_pkgs"; database.get_explicitly_installed_pkgs_async.begin ((obj, res) => { if (current_filter != "explicitly_installed_pkgs") { return; } remove_all_button.visible = false; populate_packages_list (database.get_explicitly_installed_pkgs_async.end (res)); }); return false; }); break; case 2: // Orphans Timeout.add (200, () => { current_filter = "orphans"; database.get_orphans_async.begin ((obj, res) => { if (current_filter != "orphans") { return; } var pkgs = database.get_orphans_async.end (res); remove_all_button.visible = pkgs.length () > 0; populate_packages_list ((owned) pkgs); }); return false; }); break; case 3: // Foreign Timeout.add (200, () => { current_filter = "foreign_pkgs"; database.get_foreign_pkgs_async.begin ((obj, res) => { if (current_filter != "foreign_pkgs") { return; } remove_all_button.visible = false; populate_packages_list (database.get_foreign_pkgs_async.end (res)); }); return false; }); break; default: break; } } [GtkCallback] void on_repos_listbox_row_activated (Gtk.ListBoxRow row) { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); unowned Gtk.Label label = row.get_child () as Gtk.Label; unowned string repo = label.label; Timeout.add (200, () => { current_filter = "repo_pkgs_%s".printf (repo); database.get_repo_pkgs_async.begin (repo, (obj, res) => { if (current_filter != "repo_pkgs_%s".printf (repo)) { return; } populate_packages_list (database.get_repo_pkgs_async.end (res)); }); return false; }); } void on_main_stack_visible_child_changed () { switch (main_stack.visible_child_name) { case "browse": main_stack_switcher.visible = true; button_back.visible = (browse_stack.visible_child_name == "browse" && filters_stack.visible_child_name != "filters"); if (browse_stack.visible_child_name == "browse") { if (filters_stack.visible_child_name == "categories") { header_filter_label.set_markup ("<b>%s</b>".printf (dgettext (null, "Categories"))); } else if (filters_stack.visible_child_name == "groups") { header_filter_label.set_markup ("<b>%s</b>".printf (dgettext (null, "Groups"))); } else if (filters_stack.visible_child_name == "repos") { header_filter_label.set_markup ("<b>%s</b>".printf (dgettext (null, "Repositories"))); } else { header_filter_label.label = ""; } } if (browse_stack.visible_child_name == "updates" || browse_stack.visible_child_name == "pending") { search_button.visible = false; } else { search_button.visible = true; } if (transaction.details_textview.buffer.get_char_count () > 0) { details_button.sensitive = true; } break; case "details": main_stack_switcher.visible = false; button_back.visible = true; header_filter_label.label = ""; search_button.visible = false; if (transaction.details_textview.buffer.get_char_count () > 0) { details_button.sensitive = true; } break; case "term": main_stack_switcher.visible = false; button_back.visible = true; header_filter_label.label = ""; search_button.visible = false; details_button.sensitive = false; details_button.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); details_button.relief = Gtk.ReliefStyle.NONE; break; default: break; } } void on_browse_stack_visible_child_changed () { refresh_packages_list (); } void on_filters_stack_visible_child_changed () { refresh_packages_list (); } void on_origin_stack_visible_child_changed () { switch (origin_stack.visible_child_name) { case "repos": sort_order_box.visible = true; // check if aur was used Gtk.TreeIter iter; if (!sort_comboboxtext.get_model ().get_iter (out iter, new Gtk.TreePath.from_indices (3, -1))) { sort_comboboxtext.append_text (dgettext (null, "Repository")); sort_comboboxtext.append_text (dgettext (null, "Size")); } break; case "aur": sort_order_box.visible = true; Gtk.TreeIter iter; // check if packages was used if (sort_comboboxtext.get_model ().get_iter (out iter, new Gtk.TreePath.from_indices (3, -1))) { if (sort_comboboxtext.active == 3 || sort_comboboxtext.active == 4) { sort_comboboxtext.active = 0; } sort_comboboxtext.remove (3); sort_comboboxtext.remove (3); } break; default: sort_order_box.visible = false; break; } } [GtkCallback] void on_menu_button_toggled () { preferences_button.sensitive = !(transaction_running || sysupgrade_running); } [GtkCallback] void on_history_button_clicked () { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); var history_dialog = new HistoryDialog (this); this.get_window ().set_cursor (null); history_dialog.show (); history_dialog.response.connect (() => { history_dialog.destroy (); }); } [GtkCallback] void on_local_button_clicked () { Gtk.FileChooserDialog chooser = new Gtk.FileChooserDialog ( dgettext (null, "Install Local Packages"), this, Gtk.FileChooserAction.OPEN, dgettext (null, "_Cancel"), Gtk.ResponseType.CANCEL, dgettext (null, "_Open"),Gtk.ResponseType.ACCEPT); chooser.window_position = Gtk.WindowPosition.CENTER_ON_PARENT; chooser.icon_name = "system-software-install"; chooser.select_multiple = true; chooser.local_only = false; chooser.create_folders = false; Gtk.FileFilter package_filter = new Gtk.FileFilter (); package_filter.set_filter_name (dgettext (null, "Alpm Package")); package_filter.add_pattern ("*.pkg.tar.xz"); chooser.add_filter (package_filter); if (chooser.run () == Gtk.ResponseType.ACCEPT) { SList<string> packages_paths = chooser.get_filenames (); if (packages_paths.length () != 0) { foreach (unowned string path in packages_paths) { to_load.add (path); } chooser.destroy (); run_transaction (); } } else { chooser.destroy (); } } [GtkCallback] void on_preferences_button_clicked () { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); run_preferences_dialog (); } public void run_preferences_dialog () { transaction.get_authorization_finished.connect (launch_preferences_dialog); transaction.start_get_authorization (); } void launch_preferences_dialog (bool authorized) { transaction.get_authorization_finished.disconnect (launch_preferences_dialog); if (authorized) { var preferences_dialog = new PreferencesDialog (transaction); preferences_dialog.run (); preferences_dialog.destroy (); } on_run_preferences_dialog_finished (); } void on_run_preferences_dialog_finished () { if (browse_stack.visible_child_name == "updates") { database.get_updates.begin (on_get_updates_finished); origin_stack.visible_child_name = "checking"; } else { this.get_window ().set_cursor (null); } } [GtkCallback] void on_about_button_clicked () { string[] authors = {"Guillaume Benoit"}; Gtk.show_about_dialog ( this, "program_name", "Pamac", "icon_name", "system-software-install", "logo_icon_name", "system-software-install", "comments", dgettext (null, "A Gtk3 frontend for libalpm"), "copyright", "Copyright © 2019 Guillaume Benoit", "authors", authors, "version", VERSION, "license_type", Gtk.License.GPL_3_0, "website", "https://gitlab.manjaro.org/applications/pamac"); } [GtkCallback] void on_details_button_clicked () { important_details = false; main_stack.visible_child_name = "term"; } [GtkCallback] void on_apply_button_clicked () { if (browse_stack.visible_child_name == "updates" && main_stack.visible_child_name == "browse") { force_refresh = false; transaction.no_confirm_upgrade = true; run_sysupgrade (); } else if (main_stack.visible_child_name == "details" && properties_stack.visible_child_name == "build_files") { transaction.save_build_files.begin (current_package_displayed, () => { run_transaction (); }); } else { run_transaction (); } details_button.sensitive = true; } void run_transaction () { transaction.no_confirm_upgrade = false; transaction_running = true; apply_button.sensitive = false; cancel_button.sensitive = false; show_transaction_infobox (); string[] to_install_ = {}; string[] to_remove_ = {}; string[] to_load_ = {}; string[] to_build_ = {}; foreach (unowned string name in to_install) { to_install_ += name; previous_to_install.add (name); } foreach (unowned string name in to_remove) { to_remove_ += name; previous_to_remove.add (name); } foreach (unowned string path in to_load) { to_load_ += path; } foreach (unowned string name in to_build) { to_build_ += name; previous_to_build.add (name); } transaction.start (to_install_, to_remove_, to_load_, to_build_, {}, {}); clear_lists (); } void run_sysupgrade () { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); sysupgrade_running = true; apply_button.sensitive = false; cancel_button.sensitive = false; string[] temp_ign_pkgs = {}; foreach (unowned string name in temporary_ignorepkgs) { temp_ign_pkgs += name; } show_transaction_infobox (); transaction.start_sysupgrade (force_refresh, database.config.enable_downgrade, temp_ign_pkgs, {}); } [GtkCallback] void on_cancel_button_clicked () { if (waiting) { waiting = false; transaction.cancel (); transaction.stop_progressbar_pulse (); set_pendings_operations (); } else if (transaction_running) { transaction_running = false; transaction.cancel (); } else if (sysupgrade_running) { sysupgrade_running = false; transaction.cancel (); } else { clear_lists (); set_pendings_operations (); scroll_to_top = false; refresh_packages_list (); if (main_stack.visible_child_name == "details") { if (database.is_installed_pkg (current_package_displayed) || database.is_sync_pkg (current_package_displayed)) { display_package_properties (current_package_displayed); } else { display_aur_properties (current_package_displayed); } } } } [GtkCallback] void on_refresh_button_clicked () { force_refresh = true; transaction.no_confirm_upgrade = false; run_sysupgrade (); } void on_get_updates_progress (uint percent) { checking_label.set_markup ("<big><b>%s %u %</b></big>".printf (dgettext (null, "Checking for Updates"), percent)); } void on_get_updates_finished (Object? source_object, AsyncResult res) { var updates = database.get_updates.end (res); // copy updates in lists (keep a ref of them) repos_updates = new List<Package> (); foreach (unowned Package pkg in updates.repos_updates) { repos_updates.append (pkg); } aur_updates = new List<AURPackage> (); foreach (unowned AURPackage pkg in updates.aur_updates) { aur_updates.append (pkg); } if (browse_stack.visible_child_name == "updates") { populate_updates (); } else { this.get_window ().set_cursor (null); } } void populate_updates () { to_update.remove_all (); if ((repos_updates.length () + aur_updates.length ()) == 0) { if (!transaction_running && !sysupgrade_running) { hide_transaction_infobox (); } hide_sidebar (); origin_stack.visible_child_name = "updated"; this.get_window ().set_cursor (null); } else { if (repos_updates.length () > 0) { foreach (unowned Package pkg in repos_updates) { if (!temporary_ignorepkgs.contains (pkg.name)) { to_update.add (pkg.name); } } } if (aur_updates.length () > 0) { foreach (unowned AURPackage pkg in aur_updates) { if (!temporary_ignorepkgs.contains (pkg.name)) { to_update.add (pkg.name); } } show_sidebar (); } if (repos_updates.length () > 0) { updates_listbox.get_row_at_index (0).activate (); } else { updates_listbox.get_row_at_index (1).activate (); } set_pendings_operations (); } } void on_start_waiting () { waiting = true; cancel_button.sensitive = true; } void on_stop_waiting () { waiting = false; cancel_button.sensitive = false; } void on_start_preparing () { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); cancel_button.sensitive = false; } void on_stop_preparing () { cancel_button.sensitive = false; this.get_window ().set_cursor (null); // restore build_files_notebook if (properties_listbox.get_selected_row ().get_index () == 3) { properties_stack.visible_child_name = "build_files"; } } void on_start_downloading () { cancel_button.sensitive = true; } void on_stop_downloading () { cancel_button.sensitive = false; } void on_start_building () { cancel_button.sensitive = true; } void on_stop_building () { cancel_button.sensitive = false; } void on_important_details_outpout (bool must_show) { if (must_show) { main_stack.visible_child_name = "term"; button_back.visible = false; } else if (main_stack.visible_child_name != "term") { important_details = true; details_button.relief = Gtk.ReliefStyle.NORMAL; details_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); } } void on_start_generating_mirrors_list () { generate_mirrors_list = true; apply_button.sensitive = false; details_button.sensitive = true; show_transaction_infobox (); } void on_generate_mirrors_list_finished () { generate_mirrors_list = false; } void on_transaction_finished (bool success) { if (!success) { foreach (unowned string name in previous_to_install) { if (!database.is_installed_pkg (name)) { to_install.add (name); } } foreach (unowned string name in previous_to_remove) { if (database.is_installed_pkg (name)) { to_remove.add (name); } } foreach (unowned string name in previous_to_build) { if (!database.is_installed_pkg (name)) { to_build.add (name); } } } transaction.transaction_summary.remove_all (); clear_previous_lists (); scroll_to_top = false; if (main_stack.visible_child_name == "details") { if (database.is_installed_pkg (current_package_displayed) || database.is_sync_pkg (current_package_displayed)) { display_package_properties (current_package_displayed); } else { display_aur_properties (current_package_displayed); } } else if (main_stack.visible_child_name == "term") { button_back.visible = true; } if (sysupgrade_running) { sysupgrade_running = false; } else { transaction_running = false; generate_mirrors_list = false; } refresh_listbox_buttons (); set_pendings_operations (); } } }