Merge pull request #12 from D3V1L0N/master

[add] package search windowing option.
This commit is contained in:
Eshan Roy (Eshanized)
2024-04-24 10:43:43 +05:30
committed by GitHub
6 changed files with 1326 additions and 3 deletions

View File

@@ -1,11 +1,11 @@
- name: "Display Package Versions"
description: "<True/False>"
description: "Show package version labels alongside the package description <True/False>"
enabled: False
- name: "Display Package Progress"
description: "<True/False>"
description: "Show the package install/uninstall progress window <True/False>"
enabled: False
- name: "Debug Loggings"
description: "<True/False>"
description: "Enable debug logging for more verbose app logging <True/False>"
enabled: False

View File

@@ -0,0 +1,542 @@
# This class is used to create a window for package name searches and to display package information
import os
import gi
import Functions as fn
from ui.MessageDialog import MessageDialog
from gi.repository import Gtk, Gdk, GdkPixbuf, Pango, GLib
gi.require_version("Gtk", "3.0")
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
class PackageSearchWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.headerbar = Gtk.HeaderBar()
self.headerbar.set_title("Package Search")
self.headerbar.set_show_close_button(True)
# remove the focus on startup from search entry
self.headerbar.set_property("can-focus", True)
Gtk.Window.grab_focus(self.headerbar)
self.set_resizable(True)
self.set_size_request(700, 500)
self.set_border_width(10)
self.set_titlebar(self.headerbar)
self.set_icon_from_file(os.path.join(base_dir, "images/blackbox.png"))
self.search_package_activated = False
self.build_gui()
def build_gui(self):
self.stack = Gtk.Stack()
self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
self.stack.set_transition_duration(350)
self.stack.set_hhomogeneous(False)
self.stack.set_vhomogeneous(False)
stack_switcher = Gtk.StackSwitcher()
stack_switcher.set_orientation(Gtk.Orientation.HORIZONTAL)
stack_switcher.set_stack(self.stack)
stack_switcher.set_homogeneous(True)
searchentry = Gtk.SearchEntry()
searchentry.set_placeholder_text("Search using package name...")
searchentry.set_size_request(400, 0)
searchentry.connect("activate", self.on_search_package_activated)
searchentry.connect("icon-release", self.on_search_package_cleared)
btn_ok = Gtk.Button(label="OK")
btn_ok.set_size_request(100, 30)
btn_ok.connect("clicked", self.on_close)
btn_ok.set_halign(Gtk.Align.END)
grid_bottom = Gtk.Grid()
grid_bottom.attach(btn_ok, 0, 1, 1, 1)
grid_bottom.set_halign(Gtk.Align.END)
vbox_bottom = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
lbl_padding_bottom = Gtk.Label(xalign=0, yalign=0)
lbl_padding_bottom.set_text("")
vbox_bottom.pack_start(lbl_padding_bottom, False, True, 0)
vbox_bottom.pack_start(grid_bottom, False, True, 0)
self.stack.add_titled(searchentry, "Package Search", "Package Search")
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
vbox.set_border_width(10)
vbox.pack_start(stack_switcher, False, False, 0)
vbox.pack_start(self.stack, False, False, 0)
vbox.pack_end(vbox_bottom, False, True, 0)
self.add(vbox)
self.show_all()
thread_pacman_sync_file_db = fn.threading.Thread(
name="thread_pacman_sync_file_db",
target=fn.sync_file_db,
daemon=True,
)
thread_pacman_sync_file_db.start()
def on_close(self, widget):
self.hide()
self.destroy()
def on_search_package_activated(self, searchentry):
if searchentry.get_text_length() == 0 and self.search_package_activated:
self.search_package_activated = False
self.stack.get_child_by_name("Package Information").destroy()
self.stack.get_child_by_name("Package Files").destroy()
Gtk.Window.grab_focus(self.headerbar)
else:
self.perform_search(searchentry)
def on_search_package_cleared(self, searchentry, icon_pos, event):
searchentry.set_placeholder_text("Search using package name...")
if self.search_package_activated is True:
self.search_package_activated = False
self.stack.get_child_by_name("Package Information").destroy()
self.stack.get_child_by_name("Package Files").destroy()
Gtk.Window.grab_focus(self.headerbar)
def perform_search(self, searchentry):
try:
if (
len(searchentry.get_text().rstrip().lstrip()) > 0
and not searchentry.get_text().isspace()
):
term = searchentry.get_text().rstrip().lstrip()
if len(term) > 0:
fn.logger.info("Searching pacman file database")
package_metadata = fn.get_package_information(term)
if package_metadata is not None:
# package information
if self.search_package_activated is True:
self.stack.get_child_by_name(
"Package Information"
).destroy()
self.stack.get_child_by_name("Package Files").destroy()
box_outer = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=5
)
listbox = Gtk.ListBox()
listbox.set_selection_mode(Gtk.SelectionMode.NONE)
box_outer.pack_start(listbox, True, True, 0)
# package name
row_package_title = Gtk.ListBoxRow()
vbox_package_title = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_title.add(vbox_package_title)
lbl_package_name_title = Gtk.Label(xalign=0)
lbl_package_name_title.set_markup("<b>Package Name</b>")
lbl_package_name_value = Gtk.Label(xalign=0)
lbl_package_name_value.set_text(package_metadata["name"])
vbox_package_title.pack_start(
lbl_package_name_title, True, True, 0
)
vbox_package_title.pack_start(
lbl_package_name_value, True, True, 0
)
listbox.add(row_package_title)
# repository
row_package_repo = Gtk.ListBoxRow()
vbox_package_repo = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_repo.add(vbox_package_repo)
lbl_package_repo_title = Gtk.Label(xalign=0)
lbl_package_repo_title.set_markup("<b>Repository</b>")
lbl_package_repo_value = Gtk.Label(xalign=0)
lbl_package_repo_value.set_text(package_metadata["repository"])
vbox_package_repo.pack_start(
lbl_package_repo_title, True, True, 0
)
vbox_package_repo.pack_start(
lbl_package_repo_value, True, True, 0
)
listbox.add(row_package_repo)
# description
row_package_description = Gtk.ListBoxRow()
vbox_package_description = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_description.add(vbox_package_description)
lbl_package_description_title = Gtk.Label(xalign=0)
lbl_package_description_title.set_markup("<b>Description</b>")
lbl_package_description_value = Gtk.Label(xalign=0)
lbl_package_description_value.set_text(
package_metadata["description"]
)
vbox_package_description.pack_start(
lbl_package_description_title, True, True, 0
)
vbox_package_description.pack_start(
lbl_package_description_value, True, True, 0
)
listbox.add(row_package_description)
# arch
row_package_arch = Gtk.ListBoxRow()
vbox_package_arch = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_arch.add(vbox_package_arch)
lbl_package_arch_title = Gtk.Label(xalign=0)
lbl_package_arch_title.set_markup("<b>Architecture</b>")
lbl_package_arch_value = Gtk.Label(xalign=0)
lbl_package_arch_value.set_text(package_metadata["arch"])
vbox_package_arch.pack_start(
lbl_package_arch_title, True, True, 0
)
vbox_package_arch.pack_start(
lbl_package_arch_value, True, True, 0
)
listbox.add(row_package_arch)
# url
row_package_url = Gtk.ListBoxRow()
vbox_package_url = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_url.add(vbox_package_url)
lbl_package_url_title = Gtk.Label(xalign=0)
lbl_package_url_title.set_markup("<b>URL</b>")
lbl_package_url_value = Gtk.Label(xalign=0)
lbl_package_url_value.set_markup(
"<a href='%s'>%s</a>"
% (package_metadata["url"], package_metadata["url"])
)
vbox_package_url.pack_start(
lbl_package_url_title, True, True, 0
)
vbox_package_url.pack_start(
lbl_package_url_value, True, True, 0
)
listbox.add(row_package_url)
# download size
row_package_size = Gtk.ListBoxRow()
vbox_package_size = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_size.add(vbox_package_size)
lbl_package_size_title = Gtk.Label(xalign=0)
lbl_package_size_title.set_markup("<b>Download size</b>")
lbl_package_size_value = Gtk.Label(xalign=0)
lbl_package_size_value.set_text(
package_metadata["download_size"]
)
vbox_package_size.pack_start(
lbl_package_size_title, True, True, 0
)
vbox_package_size.pack_start(
lbl_package_size_value, True, True, 0
)
listbox.add(row_package_size)
# installed size
row_package_installed_size = Gtk.ListBoxRow()
vbox_package_installed_size = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_installed_size.add(vbox_package_installed_size)
lbl_package_installed_size_title = Gtk.Label(xalign=0)
lbl_package_installed_size_title.set_markup(
"<b>Installed size</b>"
)
lbl_package_installed_size_value = Gtk.Label(xalign=0)
lbl_package_installed_size_value.set_text(
package_metadata["installed_size"]
)
vbox_package_installed_size.pack_start(
lbl_package_installed_size_title, True, True, 0
)
vbox_package_installed_size.pack_start(
lbl_package_installed_size_value, True, True, 0
)
listbox.add(row_package_installed_size)
# build date
row_package_build_date = Gtk.ListBoxRow()
vbox_package_build_date = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_build_date.add(vbox_package_build_date)
lbl_package_build_date_title = Gtk.Label(xalign=0)
lbl_package_build_date_title.set_markup("<b>Build date</b>")
lbl_package_build_date_value = Gtk.Label(xalign=0)
lbl_package_build_date_value.set_text(
package_metadata["build_date"]
)
vbox_package_build_date.pack_start(
lbl_package_build_date_title, True, True, 0
)
vbox_package_build_date.pack_start(
lbl_package_build_date_value, True, True, 0
)
listbox.add(row_package_build_date)
# packager
row_package_maintainer = Gtk.ListBoxRow()
vbox_package_maintainer = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_maintainer.add(vbox_package_maintainer)
lbl_package_maintainer_title = Gtk.Label(xalign=0)
lbl_package_maintainer_title.set_markup("<b>Packager</b>")
lbl_package_maintainer_value = Gtk.Label(xalign=0)
lbl_package_maintainer_value.set_text(
package_metadata["packager"]
)
vbox_package_maintainer.pack_start(
lbl_package_maintainer_title, True, True, 0
)
vbox_package_maintainer.pack_start(
lbl_package_maintainer_value, True, True, 0
)
listbox.add(row_package_maintainer)
# depends on
expander_depends_on = Gtk.Expander()
expander_depends_on.set_expanded(True)
expander_depends_on.set_use_markup(True)
expander_depends_on.set_resize_toplevel(True)
expander_depends_on.set_label("<b>Depends on</b>")
row_package_depends_on = Gtk.ListBoxRow()
expander_depends_on.add(row_package_depends_on)
vbox_package_depends_on = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_depends_on.add(vbox_package_depends_on)
if len(package_metadata["depends_on"]) > 0:
treestore_depends = Gtk.TreeStore(str, str)
for item in package_metadata["depends_on"]:
treestore_depends.append(None, list(item))
treeview_depends = Gtk.TreeView(model=treestore_depends)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Package", renderer, text=0)
treeview_depends.append_column(column)
vbox_package_depends_on.pack_start(
treeview_depends, True, True, 0
)
else:
lbl_package_depends_value = Gtk.Label(xalign=0, yalign=0)
lbl_package_depends_value.set_text("None")
vbox_package_depends_on.pack_start(
lbl_package_depends_value, True, True, 0
)
listbox.add(expander_depends_on)
# conflicts with
expander_conflicts_with = Gtk.Expander()
expander_conflicts_with.set_use_markup(True)
expander_conflicts_with.set_expanded(True)
expander_conflicts_with.set_resize_toplevel(True)
expander_conflicts_with.set_label("<b>Conflicts with</b>")
row_package_conflicts_with = Gtk.ListBoxRow()
expander_conflicts_with.add(row_package_conflicts_with)
vbox_package_conflicts_with = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_conflicts_with.add(vbox_package_conflicts_with)
if len(package_metadata["conflicts_with"]) > 0:
treestore_conflicts = Gtk.TreeStore(str, str)
for item in package_metadata["conflicts_with"]:
treestore_conflicts.append(None, list(item))
treeview_conflicts = Gtk.TreeView(model=treestore_conflicts)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Package", renderer, text=0)
treeview_conflicts.append_column(column)
vbox_package_conflicts_with.pack_start(
treeview_conflicts, True, True, 0
)
else:
lbl_package_conflicts_with_value = Gtk.Label(
xalign=0, yalign=0
)
lbl_package_conflicts_with_value.set_text("None")
vbox_package_conflicts_with.pack_start(
lbl_package_conflicts_with_value, True, True, 0
)
listbox.add(expander_conflicts_with)
checkbtn_installed = Gtk.CheckButton(label="Installed")
checkbtn_installed.set_active(False)
checkbtn_installed.set_sensitive(False)
# is the package installed
installed = fn.check_package_installed(term)
if installed is True:
checkbtn_installed.set_active(True)
# box_outer.pack_start(checkbtn_installed, True, True, 0)
scrolled_window_package_info = Gtk.ScrolledWindow()
scrolled_window_package_info.set_propagate_natural_height(True)
scrolled_window_package_info.add(box_outer)
vbox_package_info = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
lbl_padding_vbox = Gtk.Label(xalign=0, yalign=0)
lbl_padding_vbox.set_text("")
vbox_package_info.pack_start(
scrolled_window_package_info, True, True, 0
)
vbox_package_info.pack_start(lbl_padding_vbox, True, True, 0)
vbox_package_info.pack_start(checkbtn_installed, True, True, 0)
self.stack.add_titled(
vbox_package_info,
"Package Information",
"Package Information",
)
# package files
package_files = fn.get_package_files(term)
if package_files is not None:
lbl_package_title = Gtk.Label(xalign=0, yalign=0)
lbl_package_title.set_markup("<b>Package</b>")
lbl_package_title_value = Gtk.Label(xalign=0, yalign=0)
lbl_package_title_value.set_text(package_metadata["name"])
treestore_filelist = Gtk.TreeStore(str, str)
for file in package_files:
treestore_filelist.append(None, list(file))
treeview_files = Gtk.TreeView(model=treestore_filelist)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Files", renderer, text=0)
treeview_files.append_column(column)
vbox_package_files = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
vbox_package_files.pack_start(
lbl_package_title, True, True, 0
)
vbox_package_files.pack_start(
lbl_package_title_value, True, True, 0
)
lbl_padding_package_files = Gtk.Label(xalign=0, yalign=0)
lbl_padding_package_files.set_text("")
vbox_package_files.pack_start(
lbl_padding_package_files, True, True, 0
)
scrolled_window_package_files = Gtk.ScrolledWindow()
scrolled_window_package_files.set_propagate_natural_height(
True
)
scrolled_window_package_files.add(treeview_files)
vbox_package_files.pack_start(
scrolled_window_package_files, True, True, 0
)
self.stack.add_titled(
vbox_package_files,
"Package Files",
"Package Files",
)
self.search_package_activated = True
self.show_all()
else:
message_dialog = MessageDialog(
"Info",
"Search returned 0 results",
"Failed to find package name",
"Are the correct pacman mirrorlists configured ?\nOr try to search again using the exact package name",
"info",
False,
)
message_dialog.show_all()
message_dialog.run()
message_dialog.hide()
except Exception as e:
fn.logger.error("Exception in perform_search(): %s" % e)

View File

@@ -0,0 +1,223 @@
import os
import gi
import Functions as fn
from queue import Queue
from ui.MessageDialog import MessageDialog
from gi.repository import Gtk, Gdk, GdkPixbuf, Pango, GLib
gi.require_version("Gtk", "3.0")
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
class PackagesImportDialog(Gtk.Dialog):
"""create a gui"""
def __init__(self, package_file, packages_list, logfile):
Gtk.Dialog.__init__(self)
# Create a queue for storing package import messages from pacman
self.pkg_import_queue = Queue()
# Create a queue for storing package install errors
self.pkg_err_queue = Queue()
# Create a queue for storing package install status
self.pkg_status_queue = Queue()
self.package_file = package_file
self.packages_list = packages_list
self.logfile = logfile
self.stop_thread = False
self.set_resizable(True)
self.set_border_width(10)
self.set_size_request(800, 700)
self.set_modal(True)
headerbar = Gtk.HeaderBar()
headerbar.set_title("Import packages")
headerbar.set_show_close_button(True)
self.set_titlebar(headerbar)
self.set_icon_from_file(os.path.join(base_dir, "images/blackbox.png"))
hbox_title = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
lbl_packages_title = Gtk.Label(xalign=0)
lbl_packages_title.set_name("title")
lbl_packages_title.set_text("Packages")
hbox_title.pack_start(lbl_packages_title, False, False, 0)
hbox_title_install = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
label_install_title = Gtk.Label(xalign=0)
label_install_title.set_markup("<b> Install Packages</b>")
hbox_title_install.pack_start(label_install_title, False, False, 0)
hbox_sep = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
hsep = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
hbox_sep.pack_start(hsep, True, True, 0)
frame_install = Gtk.Frame(label="")
frame_install_label = frame_install.get_label_widget()
frame_install_label.set_markup("<b>Install Packages</b>")
hbox_install = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
label_install_desc = Gtk.Label(xalign=0, yalign=0)
label_install_desc.set_markup(
f""
f" <b>WARNING: Proceed with caution this will install packages onto your system!</b>\n"
f" <b>Packages from the AUR are not supported </b>\n"
f" <b>This also performs a full system upgrade</b>\n\n"
f" - A list of packages are sourced from <b>{self.package_file}</b>\n"
f" - To ignore a package, add a # in front of the package name\n"
f" - Log file: {self.logfile}\n"
f" - <b>A reboot is recommended when core Linux packages are installed</b>\n"
)
self.scrolled_window = Gtk.ScrolledWindow()
self.textview = Gtk.TextView()
self.textview.set_name("textview_log")
self.textview.set_property("editable", False)
self.textview.set_property("monospace", True)
self.textview.set_border_width(10)
self.textview.set_vexpand(True)
self.textview.set_hexpand(True)
msg_buffer = self.textview.get_buffer()
msg_buffer.insert(
msg_buffer.get_end_iter(),
"\n Click Yes to confirm install of the following packages:\n\n",
)
lbl_title_message = Gtk.Label(xalign=0, yalign=0)
lbl_title_message.set_markup(
"There are <b>%s</b> packages to install, proceed ?"
% len(self.packages_list)
)
lbl_padding1 = Gtk.Label(xalign=0, yalign=0)
lbl_padding1.set_text("")
lbl_padding2 = Gtk.Label(xalign=0, yalign=0)
lbl_padding2.set_text("")
self.infobar = Gtk.InfoBar()
content = self.infobar.get_content_area()
content.add(lbl_title_message)
self.infobar.set_revealed(True)
for package in sorted(self.packages_list):
msg_buffer.insert(msg_buffer.get_end_iter(), " - %s\n" % package)
# move focus away from the textview, to hide the cursor at load
headerbar.set_property("can-focus", True)
Gtk.Window.grab_focus(headerbar)
self.scrolled_window.add(self.textview)
self.button_yes = self.add_button("Yes", Gtk.ResponseType.OK)
self.button_yes.set_size_request(100, 30)
btn_yes_context = self.button_yes.get_style_context()
btn_yes_context.add_class("destructive-action")
self.button_no = self.add_button("Close", Gtk.ResponseType.CANCEL)
self.button_no.set_size_request(100, 30)
self.connect("response", self.on_response)
vbox_log_dir = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
btn_open_log_dir = Gtk.Button(label="Open log directory")
btn_open_log_dir.connect("clicked", self.on_open_log_dir_clicked)
btn_open_log_dir.set_size_request(100, 30)
vbox_log_dir.pack_start(btn_open_log_dir, False, False, 0)
grid_message = Gtk.Grid()
grid_message.attach(label_install_desc, 0, 0, 1, 1)
grid_message.attach(self.infobar, 0, 1, 1, 1)
grid_message.attach(lbl_padding1, 0, 2, 1, 1)
grid_message.attach(self.scrolled_window, 0, 3, 1, 1)
grid_message.attach(lbl_padding2, 0, 4, 1, 1)
grid_message.attach(vbox_log_dir, 0, 5, 1, 1)
self.vbox.add(grid_message)
def on_open_log_dir_clicked(self, widget):
fn.open_log_dir()
def display_progress(self):
self.textview.destroy()
self.infobar.destroy()
self.button_yes.destroy()
self.label_package_status = Gtk.Label(xalign=0, yalign=0)
self.label_package_count = Gtk.Label(xalign=0, yalign=0)
label_warning_close = Gtk.Label(xalign=0, yalign=0)
label_warning_close.set_markup(
"<b>Do not close this window during package installation</b>"
)
self.textview = Gtk.TextView()
self.textview.set_name("textview_log")
self.textview.set_property("editable", False)
self.textview.set_property("monospace", True)
self.textview.set_border_width(10)
self.textview.set_vexpand(True)
self.textview.set_hexpand(True)
self.scrolled_window.add(self.textview)
self.msg_buffer = self.textview.get_buffer()
self.vbox.add(label_warning_close)
self.vbox.add(self.label_package_status)
self.vbox.add(self.label_package_count)
fn.Thread(
target=fn.monitor_package_import,
args=(self,),
daemon=True,
).start()
self.show_all()
fn.logger.info("Installing packages")
event = "%s [INFO]: Installing packages\n" % fn.datetime.now().strftime(
"%Y-%m-%d-%H-%M-%S"
)
fn.logger.info("Log file = %s" % self.logfile)
self.pkg_import_queue.put(event)
# debug install, overrride packages_list
# starts 2 threads one to install the packages, and another to check install status
fn.Thread(
target=fn.import_packages,
args=(self,),
daemon=True,
).start()
fn.Thread(target=fn.log_package_status, args=(self,), daemon=True).start()
def on_response(self, dialog, response):
if response in (Gtk.ResponseType.OK, Gtk.ResponseType.YES):
self.stop_thread = False
self.display_progress()
else:
self.stop_thread = True
dialog.hide()
dialog.destroy()

View File

@@ -0,0 +1,71 @@
# This class is used to create a window to monitor the pacman log file inside /var/log/pacman.log
import os
import gi
import Functions as fn
from gi.repository import Gtk, Gdk, GdkPixbuf, Pango, GLib
gi.require_version("Gtk", "3.0")
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
# base_dir = os.path.dirname(os.path.realpath(__file__))
class PacmanLogWindow(Gtk.Window):
def __init__(self, textview_pacmanlog, btn_pacmanlog):
Gtk.Window.__init__(self)
self.start_logtimer = True
self.textview_pacmanlog = textview_pacmanlog
self.btn_pacmanlog = btn_pacmanlog
headerbar = Gtk.HeaderBar()
headerbar.set_show_close_button(True)
self.set_titlebar(headerbar)
self.set_title("BlackBox - Pacman log file viewer")
self.set_default_size(800, 600)
self.set_resizable(True)
self.set_border_width(10)
self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
self.set_icon_from_file(os.path.join(base_dir, "images/blackbox.png"))
self.connect("delete-event", self.on_close)
btn_pacmanlog_ok = Gtk.Button(label="OK")
btn_pacmanlog_ok.connect("clicked", self.on_response, "response")
btn_pacmanlog_ok.set_size_request(100, 30)
btn_pacmanlog_ok.set_halign(Gtk.Align.END)
pacmanlog_scrolledwindow = Gtk.ScrolledWindow()
pacmanlog_scrolledwindow.set_size_request(750, 500)
pacmanlog_scrolledwindow.add(self.textview_pacmanlog)
lbl_padding1 = Gtk.Label(xalign=0, yalign=0)
lbl_padding1.set_text("")
vbox_pacmanlog = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
vbox_pacmanlog.pack_start(pacmanlog_scrolledwindow, True, True, 0)
vbox_pacmanlog.pack_start(lbl_padding1, False, False, 0)
vbox_pacmanlog.pack_start(btn_pacmanlog_ok, False, False, 0)
self.add(vbox_pacmanlog)
def on_close(self, widget, data):
fn.logger.debug("Closing pacman log monitoring window")
self.start_logtimer = False
self.btn_pacmanlog.set_sensitive(True)
self.hide()
self.destroy()
def on_response(self, widget, response):
# stop updating the textview
fn.logger.debug("Closing pacman log monitoring dialog")
self.start_logtimer = False
self.btn_pacmanlog.set_sensitive(True)
# self.remove(self)
self.hide()
self.destroy()

View File

@@ -0,0 +1,87 @@
from gi.repository import Gtk, GLib
import gi
# Since a system can have multiple versions
# of GTK + installed, we want to make
# sure that we are importing GTK + 3.
gi.require_version("Gtk", "3.0")
class ProgressBarWindow(Gtk.Window):
new_value = 0.0
def __init__(self):
Gtk.Window.__init__(self, title="Progress Bar")
self.set_border_width(10)
vbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
self.add(vbox)
# Create a ProgressBar
self.progressbar = Gtk.ProgressBar()
vbox.pack_start(self.progressbar, True, True, 0)
# Create CheckButton with labels "Show text",
# "Activity mode", "Right to Left" respectively
# button = Gtk.CheckButton(label="Show text")
# button.connect("toggled", self.on_show_text_toggled)
# vbox.pack_start(button, True, True, 0)
# button = Gtk.CheckButton(label="Activity mode")
# button.connect("toggled", self.on_activity_mode_toggled)
# vbox.pack_start(button, True, True, 0)
# button = Gtk.CheckButton(label="Right to Left")
# button.connect("toggled", self.on_right_to_left_toggled)
# vbox.pack_start(button, True, True, 0)
# self.timeout_id = GLib.timeout_add(5000, self.on_timeout, None)
self.activity_mode = False
def set_text(self, text):
self.progressbar.set_text(text)
self.progressbar.set_show_text(True)
def reset_timer(self):
new_value = 0.0
self.progressbar.set_fraction(new_value)
def on_activity_mode_toggled(self, button):
self.activity_mode = button.get_active()
if self.activity_mode:
self.progressbar.pulse()
else:
self.progressbar.set_fraction(0.0)
def on_right_to_left_toggled(self, button):
value = button.get_active()
self.progressbar.set_inverted(value)
def update(self, fraction):
new_value = self.progressbar.get_fraction() + fraction
self.progressbar.set_fraction(new_value)
if new_value >= 1.0:
return False
return True
def get_complete(self):
if self.progressbar.get_fraction() >= 1.0:
return True
return False
def on_timeout(self, user_data=0.01):
"""
Update value on the progress bar
"""
if self.activity_mode:
self.progressbar.pulse()
else:
new_value = self.progressbar.get_fraction() + user_data
if new_value > 1:
new_value = 0.0
return False
self.progressbar.set_fraction(new_value)
return True

View File

@@ -0,0 +1,400 @@
# This class is used to create a modal dialog window showing progress of a package install/uninstall and general package information
import os
import gi
import Functions as fn
from ui.MessageDialog import MessageDialog
from gi.repository import Gtk, Gdk, GdkPixbuf, Pango, GLib
gi.require_version("Gtk", "3.0")
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
# base_dir = os.path.dirname(os.path.realpath(__file__))
class ProgressDialog(Gtk.Dialog):
def __init__(self, action, package, command, package_metadata):
Gtk.Dialog.__init__(self)
self.package_found = True
# this gets package information using pacman -Si or pacman -Qi whichever returns output
# package_metadata = fn.get_package_information(pkg.name)
# if a mirrorlist isn't configured properly, pacman will not be able to query its repository
# so the following is a condition to make sure the data returned isn't an error
if type(package_metadata) is dict:
package_progress_dialog_headerbar = Gtk.HeaderBar()
package_progress_dialog_headerbar.set_show_close_button(True)
self.set_titlebar(package_progress_dialog_headerbar)
self.connect("delete-event", package_progress_dialog_on_close, self, action)
if action == "install":
self.set_title("BlackBox - installing package %s" % package.name)
elif action == "uninstall":
self.set_title("BlackBox - removing package %s" % package.name)
self.btn_package_progress_close = Gtk.Button(label="OK")
self.btn_package_progress_close.connect(
"clicked",
on_package_progress_close_response,
self,
)
self.btn_package_progress_close.set_sensitive(False)
self.btn_package_progress_close.set_size_request(100, 30)
self.btn_package_progress_close.set_halign(Gtk.Align.END)
self.set_resizable(True)
self.set_size_request(850, 700)
self.set_modal(True)
self.set_border_width(10)
self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
self.set_icon_from_file(os.path.join(base_dir, "images/blackbox.png"))
lbl_pacman_action_title = Gtk.Label(xalign=0, yalign=0)
lbl_pacman_action_title.set_text("Running command:")
lbl_pacman_action_value = Gtk.Label(xalign=0, yalign=0)
lbl_pacman_action_value.set_markup("<b>%s</b>" % command)
stack = Gtk.Stack()
stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
stack.set_transition_duration(350)
stack.set_hhomogeneous(False)
stack.set_vhomogeneous(False)
stack_switcher = Gtk.StackSwitcher()
stack_switcher.set_orientation(Gtk.Orientation.HORIZONTAL)
stack_switcher.set_stack(stack)
stack_switcher.set_homogeneous(True)
package_progress_grid = Gtk.Grid()
self.infobar = Gtk.InfoBar()
self.infobar.set_name("infobar_info")
content = self.infobar.get_content_area()
content.add(lbl_pacman_action_title)
content.add(lbl_pacman_action_value)
self.infobar.set_revealed(True)
lbl_padding_header1 = Gtk.Label(xalign=0, yalign=0)
lbl_padding_header1.set_text("")
package_progress_grid.attach(lbl_padding_header1, 0, 1, 1, 1)
package_progress_grid.attach(self.infobar, 0, 2, 1, 1)
package_progress_grid.set_property("can-focus", True)
Gtk.Window.grab_focus(package_progress_grid)
lbl_padding1 = Gtk.Label(xalign=0, yalign=0)
lbl_padding1.set_text("")
lbl_padding2 = Gtk.Label(xalign=0, yalign=0)
lbl_padding2.set_text("")
lbl_padding2.set_halign(Gtk.Align.END)
package_progress_grid.attach(lbl_padding1, 0, 3, 1, 1)
package_progress_scrolled_window = Gtk.ScrolledWindow()
self.package_progress_textview = Gtk.TextView()
self.package_progress_textview.set_property("editable", False)
self.package_progress_textview.set_property("monospace", True)
self.package_progress_textview.set_border_width(10)
self.package_progress_textview.set_vexpand(True)
self.package_progress_textview.set_hexpand(True)
buffer = self.package_progress_textview.get_buffer()
self.package_progress_textview.set_buffer(buffer)
package_progress_scrolled_window.set_size_request(700, 430)
package_progress_scrolled_window.add(self.package_progress_textview)
package_progress_grid.attach(package_progress_scrolled_window, 0, 4, 1, 1)
vbox_close = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
vbox_close.pack_start(lbl_padding2, True, True, 0)
vbox_close.pack_start(self.btn_package_progress_close, True, True, 0)
stack.add_titled(package_progress_grid, "Progress", "Package Progress")
# package information
box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
listbox = Gtk.ListBox()
listbox.set_selection_mode(Gtk.SelectionMode.NONE)
box_outer.pack_start(listbox, True, True, 0)
# package name
row_package_title = Gtk.ListBoxRow()
vbox_package_title = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_title.add(vbox_package_title)
lbl_package_name_title = Gtk.Label(xalign=0)
lbl_package_name_title.set_markup("<b>Package Name</b>")
lbl_package_name_value = Gtk.Label(xalign=0)
lbl_package_name_value.set_text(package_metadata["name"])
vbox_package_title.pack_start(lbl_package_name_title, True, True, 0)
vbox_package_title.pack_start(lbl_package_name_value, True, True, 0)
listbox.add(row_package_title)
# repository
row_package_repo = Gtk.ListBoxRow()
vbox_package_repo = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
row_package_repo.add(vbox_package_repo)
lbl_package_repo_title = Gtk.Label(xalign=0)
lbl_package_repo_title.set_markup("<b>Repository</b>")
lbl_package_repo_value = Gtk.Label(xalign=0)
lbl_package_repo_value.set_text(package_metadata["repository"])
vbox_package_repo.pack_start(lbl_package_repo_title, True, True, 0)
vbox_package_repo.pack_start(lbl_package_repo_value, True, True, 0)
listbox.add(row_package_repo)
# description
row_package_description = Gtk.ListBoxRow()
vbox_package_description = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_description.add(vbox_package_description)
lbl_package_description_title = Gtk.Label(xalign=0)
lbl_package_description_title.set_markup("<b>Description</b>")
lbl_package_description_value = Gtk.Label(xalign=0)
lbl_package_description_value.set_text(package_metadata["description"])
vbox_package_description.pack_start(
lbl_package_description_title, True, True, 0
)
vbox_package_description.pack_start(
lbl_package_description_value, True, True, 0
)
listbox.add(row_package_description)
# arch
row_package_arch = Gtk.ListBoxRow()
vbox_package_arch = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
row_package_arch.add(vbox_package_arch)
lbl_package_arch_title = Gtk.Label(xalign=0)
lbl_package_arch_title.set_markup("<b>Architecture</b>")
lbl_package_arch_value = Gtk.Label(xalign=0)
lbl_package_arch_value.set_text(package_metadata["arch"])
vbox_package_arch.pack_start(lbl_package_arch_title, True, True, 0)
vbox_package_arch.pack_start(lbl_package_arch_value, True, True, 0)
listbox.add(row_package_arch)
# url
row_package_url = Gtk.ListBoxRow()
vbox_package_url = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
row_package_url.add(vbox_package_url)
lbl_package_url_title = Gtk.Label(xalign=0)
lbl_package_url_title.set_markup("<b>URL</b>")
lbl_package_url_value = Gtk.Label(xalign=0)
lbl_package_url_value.set_markup(
"<a href='%s'>%s</a>"
% (package_metadata["url"], package_metadata["url"])
)
vbox_package_url.pack_start(lbl_package_url_title, True, True, 0)
vbox_package_url.pack_start(lbl_package_url_value, True, True, 0)
listbox.add(row_package_url)
# download size
row_package_size = Gtk.ListBoxRow()
vbox_package_size = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
row_package_size.add(vbox_package_size)
lbl_package_size_title = Gtk.Label(xalign=0)
lbl_package_size_title.set_markup("<b>Download size</b>")
lbl_package_size_value = Gtk.Label(xalign=0)
lbl_package_size_value.set_text(package_metadata["download_size"])
vbox_package_size.pack_start(lbl_package_size_title, True, True, 0)
vbox_package_size.pack_start(lbl_package_size_value, True, True, 0)
listbox.add(row_package_size)
# installed size
row_package_installed_size = Gtk.ListBoxRow()
vbox_package_installed_size = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_installed_size.add(vbox_package_installed_size)
lbl_package_installed_size_title = Gtk.Label(xalign=0)
lbl_package_installed_size_title.set_markup("<b>Installed size</b>")
lbl_package_installed_size_value = Gtk.Label(xalign=0)
lbl_package_installed_size_value.set_text(
package_metadata["installed_size"]
)
vbox_package_installed_size.pack_start(
lbl_package_installed_size_title, True, True, 0
)
vbox_package_installed_size.pack_start(
lbl_package_installed_size_value, True, True, 0
)
listbox.add(row_package_installed_size)
# build date
row_package_build_date = Gtk.ListBoxRow()
vbox_package_build_date = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_build_date.add(vbox_package_build_date)
lbl_package_build_date_title = Gtk.Label(xalign=0)
lbl_package_build_date_title.set_markup("<b>Build date</b>")
lbl_package_build_date_value = Gtk.Label(xalign=0)
lbl_package_build_date_value.set_text(package_metadata["build_date"])
vbox_package_build_date.pack_start(
lbl_package_build_date_title, True, True, 0
)
vbox_package_build_date.pack_start(
lbl_package_build_date_value, True, True, 0
)
listbox.add(row_package_build_date)
# packager
row_package_maintainer = Gtk.ListBoxRow()
vbox_package_maintainer = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_maintainer.add(vbox_package_maintainer)
lbl_package_maintainer_title = Gtk.Label(xalign=0)
lbl_package_maintainer_title.set_markup("<b>Packager</b>")
lbl_package_maintainer_value = Gtk.Label(xalign=0)
lbl_package_maintainer_value.set_text(package_metadata["packager"])
vbox_package_maintainer.pack_start(
lbl_package_maintainer_title, True, True, 0
)
vbox_package_maintainer.pack_start(
lbl_package_maintainer_value, True, True, 0
)
listbox.add(row_package_maintainer)
# depends on
expander_depends_on = Gtk.Expander()
expander_depends_on.set_use_markup(True)
expander_depends_on.set_resize_toplevel(True)
expander_depends_on.set_label("<b>Depends on</b>")
row_package_depends_on = Gtk.ListBoxRow()
expander_depends_on.add(row_package_depends_on)
vbox_package_depends_on = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_depends_on.add(vbox_package_depends_on)
if len(package_metadata["depends_on"]) > 0:
treestore_depends = Gtk.TreeStore(str, str)
for item in package_metadata["depends_on"]:
treestore_depends.append(None, list(item))
treeview_depends = Gtk.TreeView(model=treestore_depends)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Package", renderer, text=0)
treeview_depends.append_column(column)
vbox_package_depends_on.pack_start(treeview_depends, True, True, 0)
else:
lbl_package_depends_value = Gtk.Label(xalign=0, yalign=0)
lbl_package_depends_value.set_text("None")
vbox_package_depends_on.pack_start(
lbl_package_depends_value, True, True, 0
)
listbox.add(expander_depends_on)
# conflicts with
expander_conflicts_with = Gtk.Expander()
expander_conflicts_with.set_use_markup(True)
expander_conflicts_with.set_resize_toplevel(True)
expander_conflicts_with.set_label("<b>Conflicts with</b>")
row_package_conflicts_with = Gtk.ListBoxRow()
expander_conflicts_with.add(row_package_conflicts_with)
vbox_package_conflicts_with = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0
)
row_package_conflicts_with.add(vbox_package_conflicts_with)
if len(package_metadata["conflicts_with"]) > 0:
treestore_conflicts = Gtk.TreeStore(str, str)
for item in package_metadata["conflicts_with"]:
treestore_conflicts.append(None, list(item))
treeview_conflicts = Gtk.TreeView(model=treestore_conflicts)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Package", renderer, text=0)
treeview_conflicts.append_column(column)
vbox_package_conflicts_with.pack_start(
treeview_conflicts, True, True, 0
)
else:
lbl_package_conflicts_with_value = Gtk.Label(xalign=0, yalign=0)
lbl_package_conflicts_with_value.set_text("None")
vbox_package_conflicts_with.pack_start(
lbl_package_conflicts_with_value, True, True, 0
)
listbox.add(expander_conflicts_with)
package_metadata_scrolled_window = Gtk.ScrolledWindow()
package_metadata_scrolled_window.add(box_outer)
stack.add_titled(
package_metadata_scrolled_window, "Package Information", "Information"
)
self.vbox.add(stack_switcher)
self.vbox.add(stack)
self.vbox.add(vbox_close)
def on_package_progress_close_response(self, widget):
self.pkg_dialog_closed = True
fn.logger.debug("Closing package progress dialog")
widget.hide()
widget.destroy()
def package_progress_dialog_on_close(widget, data, self, action):
self.pkg_dialog_closed = True
fn.logger.debug("Closing package progress dialog")
widget.hide()
widget.destroy()