diff --git a/blackbox/blackbox.py b/blackbox/blackbox.py index b0d5f86..8518206 100644 --- a/blackbox/blackbox.py +++ b/blackbox/blackbox.py @@ -7,6 +7,8 @@ from queue import Queue import sys import time from time import sleep +import signal + # UI modules from ui.GUI import GUI from ui.SplashScreen import SplashScreen @@ -27,6 +29,7 @@ from gi.repository import Gtk,Gdk,GdkPixbuf, Pango, GLib import Functions as fn from Settings import Settings +from requests.packages import package base_dir = os.path.dirname(os.path.realpath(__file__)) @@ -209,4 +212,513 @@ class Main(Gtk.Window): # Basic OOPS Concept ) self.search_activated = False + if searchentry.get_text_length() == 0: + self.search_activated = False + + search_term = searchentry.get_text() + if not search_term.isspace(): + try: + if len(search_term.rstrip().lstrip()) > 0: + th_search = fn.threading.Thread( + name="thread_search", + target=fn.search, + args=( + self, + search_term.rstrip().lstrip(), + ), + ) + fn.logger.info("Starting search") + th_search.start() + # get the search_results from the queue + results = self.search_queue.get() + if results is not None: + fn.logger.info("Search complete") + if len(results) > 0: + total = 0 + for val in results.values(): + total += len(val) + fn.logger.info("Search found %s results" % total) + # make sure the gui search only displays the pkgs inside the results + GUI.setup_gui_search( + self, + Gtk, + Gdk, + GdkPixbuf, + base_dir, + os, + Pango, + results, + search_term, + None, + ) + self.search_activated = True + else: + fn.logger.info("Search found %s results" % 0) + self.searchentry.grab_focus() + message_dialog = MessageDialog( + "Info", + "Search returned 0 results", + "Failed to find search term inside the package name or description.", + "Try to search again using another term", + "info", + False, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + elif self.search_activated == True: + GUI.setup_gui( + self, + Gtk, + Gdk, + GdkPixbuf, + base_dir, + os, + Pango, + None, + ) + self.search_activated = False + except Exception as err: + fn.logger.error("Exception in on_search_activated(): %s" % err) + finally: + if self.search_activated == True: + self.search_queue.task_done() + def on_search_cleared(self, searchentry, icon_pos, event): + if self.search_activated: + GUI.setup_gui( + self, + Gtk, + Gdk, + GdkPixbuf, + base_dir, + os, + Pango, + None, + ) + self.searchentry.set_placeholder_text("Search...") + self.search_activated = False + + def on_close(self, widget, data): + settings = Settings(self.display_versions, self.display_package_progress) + settings.write_config_file() + if os.path.exists(fn.blackbox_lockfile): + os.unlink(fn.blackbox_lockfile) + if os.path.exists(fn.blackbox_pidfile): + os.unlink(fn.blackbox_pidfile) + fn.terminate_pacman() + Gtk.main_quit() + print("") + print("Thanks for using BlackBox") + print("Report issues to make it even better") + print("") + print("") + print("") + + def app_toggle(self, widget, active, package): + if widget.get_state() == False and widget.get_active() == True: + if len(package.name) > 0: + inst_str = [ + "pacman", + "-S", + package.name, + "--needed", + "--noconfirm", + ] + if self.display_package_progress is True: + if fn.check_pacman_lockfile(): + widget.set_state(False) + widget.set_active(False) + proc = fn.get_pacman_process() + message_dialog = MessageDialog( + "Warning", + "Blackbox cannot proceed pacman lockfile found", + "Pacman cannot lock the db, a lockfile is found inside %s" + % fn.pacman_lockfile, + "Pacman is running: %s" % proc, + "warning", + False, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + return True + else: + package_metadata = fn.get_package_information(package.name) + if ( + type(package_metadata) is str + and package_metadata.strip() + == "error: package '%s' was not found" % package.name + ): + self.package_found = False + fn.logger.warning( + "The package %s was not found in any configured Pacman repositories" + % package.name + ) + fn.logger.warning("Package install cannot continue") + message_dialog = MessageDialog( + "Error", + "Pacman repository error: package '%s' was not found" + % package.name, + "Blackbox cannot process the request", + "Are the correct pacman mirrorlists configured ?", + "error", + False, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + widget.set_state(False) + widget.set_active(False) + return True + else: + widget.set_state(True) + widget.set_active(True) + progress_dialog = ProgressDialog( + "install", + package, + " ".join(inst_str), + package_metadata, + ) + progress_dialog.show_all() + self.pkg_queue.put( + ( + package, + "install", + widget, + inst_str, + progress_dialog, + ), + ) + th = fn.threading.Thread( + name="thread_pkginst", + target=fn.install, + args=(self,), + daemon=True, + ) + th.start() + fn.logger.debug("Package-install thread started") + else: + progress_dialog = None + widget.set_sensitive(False) + widget.set_active(True) + widget.set_state(True) + fn.logger.info("Package to install : %s" % package.name) + # another pacman transaction is running, add items to the holding queue + if ( + fn.check_pacman_lockfile() is True + and self.display_package_progress is False + ): + self.pkg_holding_queue.put( + ( + package, + "install", + widget, + inst_str, + progress_dialog, + ), + ) + if fn.is_thread_alive("thread_check_holding_queue") is False: + th = fn.threading.Thread( + target=fn.check_holding_queue, + name="thread_check_holding_queue", + daemon=True, + args=(self,), + ) + th.start() + fn.logger.debug("Check-holding-queue thread started") + elif self.display_package_progress is False: + self.pkg_queue.put( + ( + package, + "install", + widget, + inst_str, + progress_dialog, + ), + ) + th = fn.threading.Thread( + name="thread_pkginst", + target=fn.install, + args=(self,), + daemon=True, + ) + th.start() + fn.logger.debug("Package-install thread started") + # switch widget is currently toggled on + if widget.get_state() == True and widget.get_active() == False: + # Uninstall the package + if len(package.name) > 0: + uninst_str = ["pacman", "-Rs", package.name, "--noconfirm"] + fn.logger.info("Package to remove : %s" % package.name) + if fn.check_pacman_lockfile(): + widget.set_state(True) + widget.set_active(True) + fn.logger.info("Pacman lockfile found, uninstall aborted") + GLib.idle_add( + self.show_lockfile_message_dialog, + priority=GLib.PRIORITY_DEFAULT, + ) + return True + if self.display_package_progress is True: + package_metadata = fn.get_package_information(package.name) + + progress_dialog = ProgressDialog( + "uninstall", + package, + " ".join(uninst_str), + package_metadata, + ) + progress_dialog.show_all() + else: + progress_dialog = None + widget.set_active(False) + widget.set_state(False) + self.pkg_queue.put( + ( + package, + "uninstall", + widget, + uninst_str, + progress_dialog, + ), + ) + th = fn.threading.Thread( + name="thread_pkgrem", + target=fn.uninstall, + args=(self,), + daemon=True, + ) + th.start() + fn.logger.debug("Package-uninstall thread started") + + # fn.print_running_threads() + + # return True to prevent the default handler from running + return True + + # App_Frame_GUI.GUI(self, Gtk, vboxStack1, fn, category, package_file) + # widget.get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().queue_redraw() + # self.gui.hide() + # self.gui.queue_redraw() + # self.gui.show_all() + + def show_lockfile_message_dialog(self): + proc = fn.get_pacman_process() + message_dialog = MessageDialog( + "Warning", + "Blackbox cannot proceed pacman lockfile found", + "Pacman cannot lock the db, a lockfile is found inside %s" + % fn.pacman_lockfile, + "Process running = %s" % proc, + "warning", + False, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + message_dialog.destroy() + + def recache_clicked(self, widget): + fn.logger.info("Recache applications - start") + fn.cache_btn() + + def on_package_search_clicked(self, widget): + fn.logger.debug("Showing Package Search window") + self.toggle_popover() + package_search_win = PackageSearchWindow() + package_search_win.show_all() + + # def on_arcolinux_iso_packages_clicked(self, widget): + # fn.logger.debug("Showing ArcoLinux ISO Packages window") + # arcolinux_iso_packages_window = ISOPackagesWindow() + # arcolinux_iso_packages_window.show() + + def on_about_app_clicked(self, widget): + fn.logger.debug("Showing About dialog") + self.toggle_popover() + about = AboutDialog() + about.run() + about.hide() + about.destroy() + + def on_packages_export_clicked(self, widget): + self.toggle_popover() + dialog_packagelist = PackageListDialog() + dialog_packagelist.show_all() + + def on_packages_import_clicked(self, widget): + self.toggle_popover() + try: + if not os.path.exists(fn.pacman_lockfile): + package_file = "%s/packages-x86_64.txt" % (fn.export_dir,) + package_import_logfile = "%spackages-install-status-%s-%s.log" % ( + fn.log_dir, + fn.datetime.today().date(), + fn.datetime.today().time().strftime("%H-%M-%S"), + ) + if os.path.exists(package_file): + # check we have a valid file + lines = None + with open(package_file, encoding="utf-8", mode="r") as f: + lines = f.readlines() + if lines is not None: + if ( + "# This file was auto-generated by the ArchLinux Tweak Tool on" + in lines[0] + or "# This file was auto-generated by Blackbox on" + in lines[0] + ): + fn.logger.info("Package list file is valid") + packages_list = [] + for line in lines: + if not line.startswith("#"): + packages_list.append(line.strip()) + + if len(packages_list) > 0: + dialog_package_import = PackagesImportDialog( + package_file, + packages_list, + package_import_logfile, + ) + dialog_package_import.show_all() + + else: + message_dialog = MessageDialog( + "Error", + "Package file is not valid %s" % package_file, + "Export a list of packages first using the Show Installed Packages button", + "", + "error", + False, + ) + + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + else: + message_dialog = MessageDialog( + "Warning", + "Cannot locate export package file %s" % package_file, + "Export a list of packages first using the Show Installed Packages button", + "", + "warning", + False, + ) + + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + else: + message_dialog = MessageDialog( + "Error", + "Pacman lock file found %s" % fn.pacman_lockfile, + "Cannot proceed, another pacman process is running", + "", + "error", + False, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + except Exception as e: + fn.logger.error("Exception in on_packages_import_clicked(): %s" % e) + + def toggle_popover(self): + if self.popover.get_visible(): + self.popover.hide() + else: + self.popover.show_all() + + def on_settings_clicked(self, widget): + self.toggle_popover() + + def snigdhaos_keyring_toggle(self, widget, data): + # toggle is currently off, add keyring + if widget.get_state() == False and widget.get_active() == True: + fn.logger.info("Installing Snigdha OS keyring") + install_keyring = fn.install_snigdhaos_keyring() + + if install_keyring == 0: + fn.logger.info("Installation of Snigdha OS keyring = OK") + rc = fn.add_snigdhaos_repos() + if rc == 0: + fn.logger.info("Snigdha OS repos added into %s" % fn.pacman_conf) + widget.set_active(True) + else: + message_dialog = MessageDialog( + "Error", + "Failed to update pacman conf", + "Errors occurred during update of the pacman config file", + rc, + "error", + True, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + widget.set_active(False) + widget.set_state(False) + return True + + else: + message_dialog = MessageDialog( + "Error", + "Failed to install Snigdha OS keyring", + "Errors occurred during install of the Snigdha OS keyring", + "Command run = %s\n\n Error = %s" + % (install_keyring["cmd_str"], install_keyring["output"]), + "error", + True, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + widget.set_active(False) + widget.set_state(False) + return True + # toggle is currently on + if widget.get_state() == True and widget.get_active() == False: + remove_keyring = fn.remove_snigdhaos_keyring() + + if remove_keyring == 0: + fn.logger.info("Removing Snigdha OS keyring OK") + + rc = fn.remove_snigdhaos_repos() + if rc == 0: + fn.logger.info("Snigdha OS repos removed from %s" % fn.pacman_conf) + widget.set_active(False) + else: + message_dialog = MessageDialog( + "Error", + "Failed to update pacman conf", + "Errors occurred during update of the pacman config file", + rc, + "error", + True, + ) + + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + widget.set_active(True) + widget.set_state(True) + return True + else: + fn.logger.error("Failed to remove Snigdha OS keyring") + message_dialog = MessageDialog( + "Error", + "Failed to remove Snigdha OS keyring", + "Errors occurred during removal of the Snigdha OS keyring", + "Command run = %s\n\n Error = %s" + % (remove_keyring["cmd_str"], remove_keyring["output"]), + "error", + True, + ) + message_dialog.show_all() + message_dialog.run() + message_dialog.hide() + widget.set_active(False) + widget.set_state(False) + return True +