mirror of
https://github.com/Snigdha-OS/snigdhaos-blackbox.git
synced 2026-03-02 02:03:55 +01:00
no changes has been made to this file
This commit is contained in:
192
usr/share/sofirem/ui/AboutDialog.py
Normal file
192
usr/share/sofirem/ui/AboutDialog.py
Normal file
@@ -0,0 +1,192 @@
|
||||
# This class stores static information about the app, and is displayed in the about dialog
|
||||
import os
|
||||
import gi
|
||||
|
||||
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 AboutDialog(Gtk.Dialog):
|
||||
def __init__(self):
|
||||
Gtk.Dialog.__init__(self)
|
||||
|
||||
app_name = "Sofirem"
|
||||
app_title = "About Sofirem"
|
||||
app_main_description = "%s - %s" % (app_name, "Software Installer Remover")
|
||||
app_secondary_message = "Install or remove software from your ArcoLinux system"
|
||||
app_secondary_description = "Report issues to make it even better"
|
||||
app_version = "pkgversion-pkgrelease"
|
||||
app_discord = "https://discord.gg/stBhS4taje"
|
||||
app_website = "https://arcolinux.info"
|
||||
app_github = "https://github.com/arcolinux/sofirem-dev"
|
||||
app_authors = []
|
||||
app_authors.append(("Cameron Percival", None))
|
||||
app_authors.append(("Fennec", None))
|
||||
app_authors.append(("Erik Dubois", None))
|
||||
|
||||
pixbuf = GdkPixbuf.Pixbuf().new_from_file_at_size(
|
||||
os.path.join(base_dir, "images/sofirem.png"), 100, 100
|
||||
)
|
||||
app_image = Gtk.Image().new_from_pixbuf(pixbuf)
|
||||
|
||||
self.set_resizable(False)
|
||||
self.set_size_request(560, 350)
|
||||
self.set_icon_from_file(os.path.join(base_dir, "images/sofirem.png"))
|
||||
self.set_border_width(10)
|
||||
|
||||
headerbar = Gtk.HeaderBar()
|
||||
headerbar.set_show_close_button(True)
|
||||
headerbar.set_title(app_title)
|
||||
self.set_titlebar(headerbar)
|
||||
|
||||
btn_about_close = Gtk.Button(label="OK")
|
||||
btn_about_close.connect("clicked", self.on_response, "response")
|
||||
|
||||
stack = Gtk.Stack()
|
||||
stack.set_transition_type(Gtk.StackTransitionType.SLIDE_UP_DOWN)
|
||||
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)
|
||||
|
||||
lbl_main_description = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_main_description.set_markup(
|
||||
"<b> %s</b>" % app_main_description
|
||||
)
|
||||
|
||||
lbl_secondary_message = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_secondary_message.set_text(
|
||||
" %s" % app_secondary_message
|
||||
)
|
||||
|
||||
lbl_secondary_description = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_secondary_description.set_text(
|
||||
" %s" % app_secondary_description
|
||||
)
|
||||
|
||||
lbl_version = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_version.set_markup(
|
||||
" <b>Version:</b> %s" % app_version
|
||||
)
|
||||
|
||||
ivbox_about = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
ivbox_about.pack_start(app_image, True, True, 0)
|
||||
ivbox_about.pack_start(lbl_main_description, True, True, 0)
|
||||
ivbox_about.pack_start(lbl_version, True, True, 0)
|
||||
ivbox_about.pack_start(lbl_secondary_message, True, True, 0)
|
||||
ivbox_about.pack_start(lbl_secondary_description, True, True, 0)
|
||||
|
||||
stack.add_titled(ivbox_about, "About Sofirem", "About")
|
||||
|
||||
grid_support = Gtk.Grid()
|
||||
|
||||
lbl_padding1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding1.set_text(" ")
|
||||
|
||||
grid_support.attach(lbl_padding1, 0, 1, 1, 1)
|
||||
|
||||
lbl_support_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_support_title.set_markup("<b>Discord </b>")
|
||||
|
||||
lbl_support_value = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_support_value.set_markup("<a href='%s'>%s</a>" % (app_discord, app_discord))
|
||||
|
||||
lbl_website_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_website_title.set_markup("<b>ArcoLinux website </b>")
|
||||
|
||||
lbl_website_value = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_website_value.set_markup("<a href='%s'>%s</a>" % (app_website, app_website))
|
||||
|
||||
lbl_github_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_github_title.set_markup("<b>GitHub </b>")
|
||||
|
||||
lbl_github_value = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_github_value.set_markup("<a href='%s'>%s</a>" % (app_github, app_github))
|
||||
|
||||
grid_support.attach(lbl_support_title, 0, 2, 1, 1)
|
||||
|
||||
grid_support.attach_next_to(
|
||||
lbl_support_value, lbl_support_title, Gtk.PositionType.RIGHT, 20, 1
|
||||
)
|
||||
|
||||
grid_support.attach(lbl_website_title, 0, 3, 1, 1)
|
||||
grid_support.attach_next_to(
|
||||
lbl_website_value, lbl_website_title, Gtk.PositionType.RIGHT, 20, 1
|
||||
)
|
||||
|
||||
grid_support.attach(lbl_github_title, 0, 4, 1, 1)
|
||||
grid_support.attach_next_to(
|
||||
lbl_github_value, lbl_github_title, Gtk.PositionType.RIGHT, 20, 1
|
||||
)
|
||||
|
||||
stack.add_titled(grid_support, "Support", "Support")
|
||||
|
||||
box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
box_outer.set_border_width(10)
|
||||
|
||||
lbl_padding2 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding2.set_text(" ")
|
||||
|
||||
lbl_padding3 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding3.set_text(" ")
|
||||
|
||||
lbl_authors_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_authors_title.set_text(
|
||||
"The following people have contributed to the development of %s" % app_name
|
||||
)
|
||||
|
||||
listbox = Gtk.ListBox()
|
||||
listbox.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||
|
||||
box_outer.pack_start(lbl_authors_title, True, True, 0)
|
||||
box_outer.pack_start(listbox, True, True, 0)
|
||||
|
||||
treestore_authors = Gtk.TreeStore(str, str)
|
||||
for item in app_authors:
|
||||
treestore_authors.append(None, list(item))
|
||||
|
||||
treeview_authors = Gtk.TreeView(model=treestore_authors)
|
||||
|
||||
renderer = Gtk.CellRendererText()
|
||||
column = Gtk.TreeViewColumn(None, renderer, text=0)
|
||||
|
||||
treeview_authors.append_column(column)
|
||||
|
||||
path = Gtk.TreePath.new_from_indices([0])
|
||||
|
||||
selection = treeview_authors.get_selection()
|
||||
|
||||
selection.select_path(path)
|
||||
|
||||
treeview_authors.expand_all()
|
||||
treeview_authors.columns_autosize()
|
||||
|
||||
row_authors = Gtk.ListBoxRow()
|
||||
vbox_authors = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||
row_authors.add(vbox_authors)
|
||||
|
||||
vbox_authors.pack_start(treeview_authors, True, True, 0)
|
||||
|
||||
listbox.add(row_authors)
|
||||
|
||||
stack.add_titled(box_outer, "Authors", "Authors")
|
||||
|
||||
self.connect("response", self.on_response)
|
||||
|
||||
self.vbox.add(stack_switcher)
|
||||
self.vbox.add(stack)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def on_response(self, dialog, response):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
523
usr/share/sofirem/ui/AppFrameGUI.py
Normal file
523
usr/share/sofirem/ui/AppFrameGUI.py
Normal file
@@ -0,0 +1,523 @@
|
||||
# =================================================================
|
||||
# = Author: Cameron Percival =
|
||||
# =================================================================
|
||||
from socket import TIPC_ADDR_NAME
|
||||
from urllib.parse import scheme_chars
|
||||
import Functions as fn
|
||||
|
||||
|
||||
class AppFrameGUI:
|
||||
def build_ui_frame(self, Gtk, vbox_stack, category, packages_list):
|
||||
try:
|
||||
# Lets set some variables that we know we will need later
|
||||
# hboxes and items to make the page look sensible
|
||||
cat_name = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
seperator = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
lbl1 = Gtk.Label(xalign=0)
|
||||
lbl1.set_text(category)
|
||||
lbl1.set_name("title")
|
||||
hseparator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
|
||||
seperator.pack_start(hseparator, True, True, 0)
|
||||
cat_name.pack_start(lbl1, False, False, 0)
|
||||
|
||||
# Stack for the different subcategories - I like crossfade as a transition, but you choose
|
||||
stack = Gtk.Stack()
|
||||
stack.set_transition_type(Gtk.StackTransitionType.SLIDE_UP_DOWN)
|
||||
stack.set_transition_duration(350)
|
||||
stack.set_hhomogeneous(False)
|
||||
stack.set_vhomogeneous(False)
|
||||
|
||||
# Stack needs a stack switcher to allow the user to make different choices
|
||||
stack_switcher = Gtk.StackSwitcher()
|
||||
stack_switcher.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
stack_switcher.set_stack(stack)
|
||||
stack_switcher.set_homogeneous(True)
|
||||
|
||||
# We will need a vbox later for storing the stack and stack switcher together at the end
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||
|
||||
# create scroller for when/if these items go "off the page"
|
||||
scrolled_switch = Gtk.ScrolledWindow()
|
||||
scrolled_switch.add(stack_switcher)
|
||||
|
||||
# These lists will ensure that we can keep track of the individual windows and their names
|
||||
# stack of vboxes
|
||||
vbox_stacks = []
|
||||
# name of each vbox - derived from the sub category name
|
||||
vbox_stacknames = []
|
||||
sep_text = " "
|
||||
subcats = {}
|
||||
# index for the grid
|
||||
index = 0
|
||||
|
||||
"""
|
||||
Store a list of unique sub-categories
|
||||
e.g.
|
||||
|
||||
category --> applications
|
||||
sub category --> Accessories
|
||||
sub category --> Conky
|
||||
|
||||
"""
|
||||
|
||||
sub_catlabels = []
|
||||
|
||||
# store unique subcategory names into a dictionary
|
||||
|
||||
for package in packages_list:
|
||||
subcats[package.subcategory] = package
|
||||
|
||||
# we now iterate across the dictionary keys
|
||||
# each Stack has an associated subcategory
|
||||
|
||||
for subcat in subcats.keys():
|
||||
vbox_stacks.append(
|
||||
Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||
)
|
||||
# for the sub-cat page title
|
||||
sub_catlabels.append(Gtk.Label(xalign=0))
|
||||
|
||||
vbox_stacknames.append(subcat)
|
||||
# iterate across a list of packages
|
||||
|
||||
for package in packages_list:
|
||||
if package.subcategory == subcat:
|
||||
page = vbox_stacks.pop()
|
||||
|
||||
if len(sub_catlabels) > 0:
|
||||
lbl_title = sub_catlabels.pop()
|
||||
lbl_desc = Gtk.Label(xalign=0)
|
||||
lbl_desc.set_markup(
|
||||
"Description: <i><b>"
|
||||
+ package.subcategory_description
|
||||
+ "</b></i>"
|
||||
)
|
||||
lbl_title.set_markup("<b>" + package.subcategory + "</b>")
|
||||
|
||||
lbl_padding_page1 = Gtk.Label(xalign=0)
|
||||
lbl_padding_page1.set_text("")
|
||||
|
||||
page.pack_start(lbl_title, False, False, 0)
|
||||
page.pack_start(lbl_desc, False, False, 0)
|
||||
page.pack_start(lbl_padding_page1, False, False, 0)
|
||||
|
||||
grid = Gtk.Grid()
|
||||
|
||||
grid.insert_row(index)
|
||||
|
||||
lbl_sep1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_sep1.set_text(sep_text)
|
||||
grid.attach(lbl_sep1, 0, index, 1, 1)
|
||||
lbl_package = Gtk.Label(xalign=0, yalign=0) # was in for loop
|
||||
|
||||
lbl_package.set_markup("<b>%s</b>" % package.name)
|
||||
|
||||
###### switch widget starts ######
|
||||
|
||||
# construct new switch
|
||||
switch = Gtk.Switch()
|
||||
switch.set_valign(Gtk.Align.CENTER)
|
||||
|
||||
"""
|
||||
Changed to use signal state-set for switch widget.
|
||||
set_state(boolean) allows the switch state to be enabled/disabled.
|
||||
When a pkg install/uninstall fails, the switch widget is enabled/disabled inside a thread.
|
||||
|
||||
Changing the switch using set_active(bool), and using the signal notify::active
|
||||
caused a never-ending loop which would call app_toggle.
|
||||
|
||||
"""
|
||||
switch.set_state(fn.query_pkg(package.name))
|
||||
switch.connect(
|
||||
"state-set",
|
||||
self.app_toggle,
|
||||
package,
|
||||
)
|
||||
|
||||
# add switch widget to grid
|
||||
|
||||
# attach_next_to(child, sibling, side, width, height)
|
||||
|
||||
grid.attach_next_to(
|
||||
switch, lbl_sep1, Gtk.PositionType.LEFT, 1, 1
|
||||
)
|
||||
|
||||
# add space seperator next to switch
|
||||
|
||||
lbl_sep_switch = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_sep_switch.set_text(sep_text)
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_sep_switch, switch, Gtk.PositionType.LEFT, 1, 1
|
||||
)
|
||||
|
||||
###### switch widget ends ######
|
||||
|
||||
###### pkg name label widget starts ######
|
||||
|
||||
lbl_sep_package1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_sep_package1.set_text(sep_text)
|
||||
|
||||
# add space seperator next to switch for extra padding
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_sep_package1, switch, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
lbl_sep_package2 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_sep_package2.set_text(sep_text)
|
||||
|
||||
# add pkg name label widget to grid
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_package, lbl_sep_package1, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
###### pkg name label widget ends
|
||||
|
||||
###### pkg desc label widget starts ######
|
||||
|
||||
lbl_sep_package_desc = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_sep_package_desc.set_text(sep_text)
|
||||
|
||||
# add space seperator next to pkg name for extra padding
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_sep_package_desc,
|
||||
lbl_package,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
lbl_package_desc = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_package_desc.set_text(package.description)
|
||||
|
||||
# add pkg desc label widget to grid
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_package_desc,
|
||||
lbl_sep_package_desc,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
###### pkg desc label widget ends
|
||||
|
||||
##### add pkg version label widget starts #####
|
||||
|
||||
if self.display_versions is True:
|
||||
lbl_package_version = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_package_version.set_text(package.version)
|
||||
lbl_package_version.set_name("lbl_package_version")
|
||||
|
||||
lbl_sep_package_version = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_sep_package_version.set_text(sep_text)
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_sep_package_version,
|
||||
lbl_package_desc,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid.attach_next_to(
|
||||
lbl_package_version,
|
||||
lbl_sep_package_version,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
##### pkg version ends #####
|
||||
|
||||
# make the page scrollable
|
||||
grid_sc = Gtk.ScrolledWindow()
|
||||
|
||||
# hide the horizontal scrollbar showing on each grid row if the window width is resized
|
||||
grid_sc.set_policy(
|
||||
Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC
|
||||
)
|
||||
grid_sc.add(grid)
|
||||
|
||||
grid_sc.set_propagate_natural_height(True)
|
||||
# pack the grid to the page.
|
||||
|
||||
page.pack_start(grid_sc, True, True, 0)
|
||||
# save the page - put it back (now populated)
|
||||
|
||||
"""
|
||||
UI note.
|
||||
To remove the extra padding around the switch buttons
|
||||
Comment out the references to grid_sc
|
||||
Then just have page.pack_start(grid,True, True, 0)
|
||||
"""
|
||||
vbox_stacks.append(page)
|
||||
|
||||
# reset the things that we need to.
|
||||
# packages.clear()
|
||||
grid = Gtk.Grid()
|
||||
|
||||
index += 1
|
||||
|
||||
# Now we pack the stack
|
||||
item_num = 0
|
||||
|
||||
for item in vbox_stacks:
|
||||
stack.add_titled(
|
||||
item,
|
||||
"stack" + str(item_num),
|
||||
vbox_stacknames[item_num],
|
||||
)
|
||||
item_num += 1
|
||||
|
||||
# Place the stack switcher and the stack together into a vbox
|
||||
vbox.pack_start(scrolled_switch, False, False, 0)
|
||||
|
||||
scrolled_window = Gtk.ScrolledWindow()
|
||||
scrolled_window.set_propagate_natural_height(True)
|
||||
scrolled_window.add(stack)
|
||||
vbox.pack_start(scrolled_window, True, True, 0)
|
||||
|
||||
# Stuff the vbox with the title and seperator to create the page
|
||||
vbox_stack.pack_start(cat_name, False, False, 0)
|
||||
vbox_stack.pack_start(seperator, False, False, 0)
|
||||
vbox_stack.pack_start(vbox, False, False, 0)
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in App_Frame_GUI.GUI(): %s" % e)
|
||||
|
||||
|
||||
########## PREVIOUS GUI CODE START ##########
|
||||
"""
|
||||
def GUI(self, Gtk, vboxStack1, category, package_file):
|
||||
try:
|
||||
# Lets set some variables that we know we will need later
|
||||
# hboxes and items to make the page look sensible
|
||||
cat_name = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
seperator = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
lbl1 = Gtk.Label(xalign=0)
|
||||
lbl1.set_text(category)
|
||||
lbl1.set_name("title")
|
||||
hseparator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
|
||||
seperator.pack_start(hseparator, True, True, 0)
|
||||
cat_name.pack_start(lbl1, False, False, 0)
|
||||
|
||||
# Stack for the different subcategories - I like crossfade as a transition, but you choose
|
||||
stack = Gtk.Stack()
|
||||
stack.set_transition_type(Gtk.StackTransitionType.SLIDE_UP_DOWN)
|
||||
stack.set_transition_duration(350)
|
||||
stack.set_hhomogeneous(False)
|
||||
stack.set_vhomogeneous(False)
|
||||
|
||||
# Stack needs a stack switcher to allow the user to make different choices
|
||||
stack_switcher = Gtk.StackSwitcher()
|
||||
stack_switcher.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
stack_switcher.set_stack(stack)
|
||||
stack_switcher.set_homogeneous(True)
|
||||
|
||||
# We will need a vbox later for storing the stack and stack switcher together at the end
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||
|
||||
# create scroller for when/if these items go "off the page"
|
||||
scrolledSwitch = Gtk.ScrolledWindow()
|
||||
scrolledSwitch.add(stack_switcher)
|
||||
|
||||
# These lists will ensure that we can keep track of the individual windows and their names
|
||||
# stack of vboxes
|
||||
vboxStacks = []
|
||||
# name of each vbox - derived from the sub category name
|
||||
vboxStackNames = []
|
||||
|
||||
# page variables - reset these when making multiple subcategories:
|
||||
# List of packages for any given subcategory
|
||||
packages = []
|
||||
# labels:
|
||||
name = ""
|
||||
description = ""
|
||||
# Lets start by reading in the package list and saving it as a file
|
||||
with open(package_file, "r") as f:
|
||||
content = f.readlines()
|
||||
# f.close()
|
||||
|
||||
# Add a line to the end of content to force the page to be packed.
|
||||
content.append(
|
||||
"pack now"
|
||||
) # Really, this can be any string, as long as it doesn't match the if statement below.
|
||||
# Now lets read the file, and use some logic to drive what goes where
|
||||
# Optomised for runspeed: the line most commonly activated appears first.
|
||||
for line in content:
|
||||
# this line will handle code in the yaml that we simply don't need or care about
|
||||
# MAINTENANCE; if the structure of the .yaml file ever changes, this WILL likely need to be updated
|
||||
if line.startswith(" packages:"):
|
||||
continue
|
||||
elif line.startswith(" - "):
|
||||
# add the package to the packages list
|
||||
package = line.strip(" - ")
|
||||
packages.append(package)
|
||||
# TODO: Add list and function to obtain package description from pacman and store it (maybe? Maybe the yaml file has what we need?)
|
||||
elif line.startswith(" description: "):
|
||||
# Set the label text for the description line
|
||||
description = (
|
||||
line.strip(" description: ").strip().strip('"').strip("\n")
|
||||
)
|
||||
else:
|
||||
# We will only hit here for category changes, or to pack the page, or if the yaml is changed.
|
||||
# Yaml changes are handled in the first if statement.
|
||||
# Pack page;
|
||||
|
||||
if len(packages) > 0:
|
||||
# Pack the page
|
||||
# Packing list:
|
||||
# vbox to pack into - pop it off the
|
||||
page = vboxStacks.pop()
|
||||
# grid it
|
||||
grid = Gtk.Grid()
|
||||
# Subcat
|
||||
lblName = Gtk.Label(xalign=0)
|
||||
lblName.set_markup("<b>" + name + "</b>")
|
||||
page.pack_start(lblName, False, False, 0)
|
||||
# description
|
||||
lblDesc = Gtk.Label(xalign=0)
|
||||
lblDesc.set_markup("Description: <i>" + description + "</i>")
|
||||
page.pack_start(lblDesc, False, False, 0)
|
||||
# packages
|
||||
sep_text = " "
|
||||
for i in range(len(packages)):
|
||||
grid.insert_row(i)
|
||||
# hbox_pkg = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||
lblSep1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lblSep1.set_text(sep_text)
|
||||
grid.attach(lblSep1, 0, i, 1, 1)
|
||||
lblPkg = Gtk.Label(xalign=0, yalign=0) # was in for loop
|
||||
|
||||
lblPkg.set_markup("<b>%s</b>" % packages[i].strip()) # was in for loop
|
||||
# hbox_pkg.pack_start(lblPkg, False, False, 100)
|
||||
###### switch widget starts ######
|
||||
|
||||
|
||||
# construct new switch
|
||||
switch = Gtk.Switch()
|
||||
|
||||
switch.set_active(Functions.query_pkg(packages[i]))
|
||||
switch.connect(
|
||||
"notify::active",
|
||||
self.app_toggle,
|
||||
packages[i],
|
||||
Gtk,
|
||||
vboxStack1,
|
||||
Functions,
|
||||
category,
|
||||
)
|
||||
|
||||
# add switch widget to grid
|
||||
|
||||
# attach_next_to(child, sibling, side, width, height)
|
||||
|
||||
grid.attach_next_to(
|
||||
switch, lblSep1, Gtk.PositionType.LEFT, 1, 1
|
||||
)
|
||||
|
||||
# add space seperator next to switch
|
||||
|
||||
lblSepSwitch = Gtk.Label(xalign=0, yalign=0)
|
||||
lblSepSwitch.set_text(sep_text)
|
||||
|
||||
grid.attach_next_to(
|
||||
lblSepSwitch, switch, Gtk.PositionType.LEFT, 1, 1
|
||||
)
|
||||
|
||||
###### switch widget ends ######
|
||||
|
||||
|
||||
###### pkg name label widget starts ######
|
||||
|
||||
lblSepPkg1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lblSepPkg1.set_text(sep_text)
|
||||
|
||||
|
||||
# add space seperator next to switch for extra padding
|
||||
|
||||
grid.attach_next_to(
|
||||
lblSepPkg1, switch, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
lblSepPkg2 = Gtk.Label(xalign=0, yalign=0)
|
||||
lblSepPkg2.set_text(sep_text)
|
||||
|
||||
# add pkg name label widget to grid
|
||||
|
||||
grid.attach_next_to(
|
||||
lblPkg, lblSepPkg1, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
###### pkg name label widget ends
|
||||
|
||||
|
||||
###### pkg desc label widget starts ######
|
||||
|
||||
lblSepPkgDesc = Gtk.Label(xalign=0, yalign=0)
|
||||
lblSepPkgDesc.set_text(sep_text)
|
||||
|
||||
# add space seperator next to pkg name for extra padding
|
||||
|
||||
grid.attach_next_to(
|
||||
lblSepPkgDesc, lblPkg, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
lblPkgDesc = Gtk.Label(xalign=0, yalign=0)
|
||||
lblPkgDesc.set_text(Functions.obtain_pkg_description(packages[i]))
|
||||
|
||||
# add pkg desc label widget to grid
|
||||
|
||||
grid.attach_next_to(
|
||||
lblPkgDesc, lblSepPkgDesc, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
###### pkg desc label widget ends
|
||||
|
||||
# make the page scrollable
|
||||
grid_sc = Gtk.ScrolledWindow()
|
||||
grid_sc.add(grid)
|
||||
|
||||
grid_sc.set_propagate_natural_height(True)
|
||||
# pack the grid to the page.
|
||||
page.pack_start(grid_sc, False, False, 0)
|
||||
# save the page - put it back (now populated)
|
||||
vboxStacks.append(page)
|
||||
# reset the things that we need to.
|
||||
packages.clear()
|
||||
grid = Gtk.Grid()
|
||||
# category change
|
||||
if line.startswith("- name: "):
|
||||
# Generate the vboxStack item and name for use later (and in packing)
|
||||
name = line.strip("- name: ").strip().strip('"')
|
||||
vboxStackNames.append(name)
|
||||
vboxStacks.append(
|
||||
Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||
)
|
||||
|
||||
# Now we pack the stack
|
||||
item_num = 0
|
||||
for item in vboxStacks:
|
||||
stack.add_titled(item, "stack" + str(item_num), vboxStackNames[item_num])
|
||||
item_num += 1
|
||||
|
||||
# Place the stack switcher and the stack together into a vbox
|
||||
vbox.pack_start(scrolledSwitch, False, False, 0)
|
||||
vbox.pack_start(stack, True, True, 0)
|
||||
|
||||
# Stuff the vbox with the title and seperator to create the page
|
||||
vboxStack1.pack_start(cat_name, False, False, 0)
|
||||
vboxStack1.pack_start(seperator, False, False, 0)
|
||||
vboxStack1.pack_start(vbox, False, False, 0)
|
||||
|
||||
except Exception as e:
|
||||
print("Exception in App_Frame_GUI.GUI(): %s" % e)
|
||||
"""
|
||||
########## PREVIOUS GUI CODE END ##########
|
||||
726
usr/share/sofirem/ui/GUI.py
Normal file
726
usr/share/sofirem/ui/GUI.py
Normal file
@@ -0,0 +1,726 @@
|
||||
# =================================================================
|
||||
# = Author: Cameron Percival =
|
||||
# =================================================================
|
||||
|
||||
|
||||
# ============Functions============
|
||||
import Functions as fn
|
||||
from ui.AppFrameGUI import AppFrameGUI
|
||||
from multiprocessing import cpu_count
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
|
||||
base_dir = fn.os.path.abspath(fn.os.path.join(fn.os.path.dirname(__file__), ".."))
|
||||
# base_dir = fn.os.path.dirname(fn.os.path.realpath(__file__))
|
||||
|
||||
|
||||
class GUI_Worker(Thread):
|
||||
def __init__(self, queue):
|
||||
Thread.__init__(self)
|
||||
self.queue = queue
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
# pull what we need from the queue so we can process properly.
|
||||
items = self.queue.get()
|
||||
|
||||
try:
|
||||
# make sure we have the required number of items on the queue
|
||||
if items is not None:
|
||||
# self, Gtk, vboxStack1, category, package_file = items
|
||||
|
||||
self, Gtk, vbox_stack, category, packages = items
|
||||
|
||||
AppFrameGUI.build_ui_frame(
|
||||
self,
|
||||
Gtk,
|
||||
vbox_stack,
|
||||
category,
|
||||
packages,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in GUI_Worker(): %s" % e)
|
||||
finally:
|
||||
if items is None:
|
||||
fn.logger.debug("Stopping GUI Worker thread")
|
||||
self.queue.task_done()
|
||||
return False
|
||||
self.queue.task_done()
|
||||
|
||||
|
||||
class GUI:
|
||||
def setup_gui_search(
|
||||
self,
|
||||
Gtk,
|
||||
Gdk,
|
||||
GdkPixbuf,
|
||||
base_dir,
|
||||
os,
|
||||
Pango,
|
||||
search_results,
|
||||
search_term,
|
||||
settings,
|
||||
):
|
||||
try:
|
||||
# remove previous vbox
|
||||
if self.search_activated == False:
|
||||
self.remove(self.vbox)
|
||||
else:
|
||||
self.remove(self.vbox_search)
|
||||
|
||||
# lets quickly create the latest installed list.
|
||||
fn.get_current_installed()
|
||||
|
||||
# =======================================================
|
||||
# HeaderBar
|
||||
# =======================================================
|
||||
|
||||
setup_headerbar(self, Gtk, settings)
|
||||
|
||||
# =======================================================
|
||||
# App Notifications
|
||||
# =======================================================
|
||||
|
||||
hbox0 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
|
||||
self.notification_revealer = Gtk.Revealer()
|
||||
self.notification_revealer.set_reveal_child(False)
|
||||
|
||||
self.notification_label = Gtk.Label()
|
||||
|
||||
pb_panel = GdkPixbuf.Pixbuf().new_from_file(base_dir + "/images/panel.png")
|
||||
panel = Gtk.Image().new_from_pixbuf(pb_panel)
|
||||
|
||||
overlay_frame = Gtk.Overlay()
|
||||
overlay_frame.add(panel)
|
||||
overlay_frame.add_overlay(self.notification_label)
|
||||
|
||||
self.notification_revealer.add(overlay_frame)
|
||||
|
||||
hbox0.pack_start(self.notification_revealer, True, False, 0)
|
||||
|
||||
# ==========================================================
|
||||
# CONTAINER
|
||||
# ==========================================================
|
||||
|
||||
self.vbox_search = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
vbox1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
|
||||
|
||||
self.vbox_search.pack_start(hbox, True, True, 0)
|
||||
self.add(self.vbox_search)
|
||||
|
||||
# ==========================================================
|
||||
# PREP WORK
|
||||
# ==========================================================
|
||||
|
||||
# This section sets up the tabs, and the array for dealing with the tab content
|
||||
|
||||
# ==========================================================
|
||||
# GENERATE STACK
|
||||
# ==========================================================
|
||||
stack = Gtk.Stack()
|
||||
# stack.set_transition_type(Gtk.StackTransitionType.SLIDE_UP_DOWN)
|
||||
stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
|
||||
stack.set_transition_duration(350)
|
||||
|
||||
vbox_stack = []
|
||||
stack_item = 0
|
||||
|
||||
# Max Threads
|
||||
"""
|
||||
Fatal Python error: Segmentation fault
|
||||
This error happens randomly, due to the for loop iteration on the cpu_count
|
||||
old code: for x in range(cpu_count()):
|
||||
"""
|
||||
|
||||
# spawn only 1 GUI_Worker threads, as any number greater causes a Segmentation fault
|
||||
|
||||
search_worker = GUI_Worker(self.queue)
|
||||
search_worker.name = "thread_GUI_search_worker"
|
||||
# Set the worker to be True to allow processing, and avoid Blocking
|
||||
# search_worker.daemon = True
|
||||
search_worker.start()
|
||||
|
||||
# This code section might look a little weird. It is because it was
|
||||
# derived from another function before this version was required.
|
||||
|
||||
for category in search_results:
|
||||
# NOTE: IF the yaml file name standard changes, be sure to update this, or weirdness will follow.
|
||||
|
||||
# subcategory = search_results[category][0].subcategory
|
||||
vbox_stack.append(
|
||||
Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||
)
|
||||
stack.add_titled(
|
||||
vbox_stack[stack_item],
|
||||
str("stack" + str(len(vbox_stack))),
|
||||
category,
|
||||
)
|
||||
|
||||
# subcategory_desc = search_results[category][0].subcategory_description
|
||||
search_res_lst = search_results[category]
|
||||
|
||||
# Multithreading!
|
||||
|
||||
self.queue.put(
|
||||
(
|
||||
self,
|
||||
Gtk,
|
||||
vbox_stack[stack_item],
|
||||
category,
|
||||
search_res_lst,
|
||||
)
|
||||
)
|
||||
|
||||
stack_item += 1
|
||||
|
||||
# send a signal that no further items are to be put on the queue
|
||||
self.queue.put(None)
|
||||
# safety to ensure that we finish threading before we continue on.
|
||||
self.queue.join()
|
||||
fn.logger.debug("GUI Worker thread completed")
|
||||
|
||||
stack_switcher = Gtk.StackSidebar()
|
||||
stack_switcher.set_name("sidebar")
|
||||
stack_switcher.set_stack(stack)
|
||||
|
||||
# =====================================================
|
||||
# LOGO
|
||||
# =====================================================
|
||||
|
||||
ivbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||
pixbuf = GdkPixbuf.Pixbuf().new_from_file_at_size(
|
||||
os.path.join(base_dir, "images/sofirem.png"), 45, 45
|
||||
)
|
||||
image = Gtk.Image().new_from_pixbuf(pixbuf)
|
||||
|
||||
# remove the focus on startup from search entry
|
||||
ivbox.set_property("can-focus", True)
|
||||
Gtk.Window.grab_focus(ivbox)
|
||||
|
||||
# =====================================================
|
||||
# RECACHE BUTTON
|
||||
# =====================================================
|
||||
|
||||
btn_recache = Gtk.Button(label="Recache Applications")
|
||||
btn_recache.connect("clicked", self.recache_clicked)
|
||||
# btnReCache.set_property("has-tooltip", True)
|
||||
# btnReCache.connect("query-tooltip", self.tooltip_callback,
|
||||
# "Refresh the application cache")
|
||||
|
||||
# =====================================================
|
||||
# REPOS
|
||||
# =====================================================
|
||||
|
||||
# if not (
|
||||
# fn.check_package_installed("arcolinux-keyring")
|
||||
# or fn.check_package_installed("arcolinux-mirrorlist-git")
|
||||
# ):
|
||||
# self.btnRepos = Gtk.Button(label="Add ArcoLinux Repo")
|
||||
# self.btnRepos._value = 1
|
||||
# else:
|
||||
# self.btnRepos = Gtk.Button(label="Remove ArcoLinux Repo")
|
||||
# self.btnRepos._value = 2
|
||||
#
|
||||
# self.btnRepos.set_size_request(100, 30)
|
||||
# self.btnRepos.connect("clicked", self.on_repos_clicked)
|
||||
|
||||
# =====================================================
|
||||
# QUIT BUTTON
|
||||
# =====================================================
|
||||
|
||||
btn_quit_app = Gtk.Button(label="Quit")
|
||||
btn_quit_app.set_size_request(100, 30)
|
||||
btn_quit_app.connect("clicked", self.on_close, "delete-event")
|
||||
btn_context = btn_quit_app.get_style_context()
|
||||
btn_context.add_class("destructive-action")
|
||||
|
||||
# =====================================================
|
||||
# SEARCH BOX
|
||||
# =====================================================
|
||||
|
||||
self.searchentry = Gtk.SearchEntry()
|
||||
self.searchentry.set_text(search_term)
|
||||
self.searchentry.connect("activate", self.on_search_activated)
|
||||
self.searchentry.connect("icon-release", self.on_search_cleared)
|
||||
|
||||
iv_searchbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
|
||||
# =====================================================
|
||||
# PACKS
|
||||
# =====================================================
|
||||
|
||||
# hbox1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=2)
|
||||
# hbox2 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=2)
|
||||
# hbox3 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=2)
|
||||
|
||||
# hbox3.pack_start(btnReCache, False, False, 0)
|
||||
|
||||
iv_searchbox.pack_start(self.searchentry, False, False, 0)
|
||||
|
||||
ivbox.pack_start(image, False, False, 0)
|
||||
ivbox.pack_start(iv_searchbox, False, False, 0)
|
||||
ivbox.pack_start(stack_switcher, True, True, 0)
|
||||
|
||||
ivbox.pack_start(btn_quit_app, False, False, 0)
|
||||
|
||||
vbox1.pack_start(hbox0, False, False, 0)
|
||||
vbox1.pack_start(stack, True, True, 0)
|
||||
|
||||
hbox.pack_start(ivbox, False, True, 0)
|
||||
hbox.pack_start(vbox1, True, True, 0)
|
||||
|
||||
stack.set_hhomogeneous(False)
|
||||
stack.set_vhomogeneous(False)
|
||||
|
||||
self.show_all()
|
||||
|
||||
except Exception as err:
|
||||
fn.logger.error("Exception in GUISearch(): %s" % err)
|
||||
|
||||
def setup_gui(self, Gtk, Gdk, GdkPixbuf, base_dir, os, Pango, settings): # noqa
|
||||
try:
|
||||
# reset back to main box
|
||||
if self.search_activated:
|
||||
# remove the search vbox
|
||||
self.remove(self.vbox_search)
|
||||
self.show_all()
|
||||
|
||||
# lets quickly create the latest installed list.
|
||||
fn.get_current_installed()
|
||||
|
||||
# =======================================================
|
||||
# HeaderBar
|
||||
# =======================================================
|
||||
|
||||
setup_headerbar(self, Gtk, settings)
|
||||
|
||||
# =======================================================
|
||||
# App Notifications
|
||||
# =======================================================
|
||||
|
||||
hbox0 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
|
||||
self.notification_revealer = Gtk.Revealer()
|
||||
self.notification_revealer.set_reveal_child(False)
|
||||
|
||||
self.notification_label = Gtk.Label()
|
||||
|
||||
pb_panel = GdkPixbuf.Pixbuf().new_from_file(base_dir + "/images/panel.png")
|
||||
panel = Gtk.Image().new_from_pixbuf(pb_panel)
|
||||
|
||||
overlay_frame = Gtk.Overlay()
|
||||
overlay_frame.add(panel)
|
||||
overlay_frame.add_overlay(self.notification_label)
|
||||
|
||||
self.notification_revealer.add(overlay_frame)
|
||||
|
||||
hbox0.pack_start(self.notification_revealer, True, False, 0)
|
||||
|
||||
# ==========================================================
|
||||
# CONTAINER
|
||||
# ==========================================================
|
||||
|
||||
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
vbox1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
|
||||
|
||||
self.vbox.pack_start(hbox, True, True, 0)
|
||||
self.add(self.vbox)
|
||||
|
||||
# ==========================================================
|
||||
# PREP WORK
|
||||
# ==========================================================
|
||||
|
||||
# This section sets up the tabs, and the array for dealing with the tab content
|
||||
"""
|
||||
yaml_files_unsorted = []
|
||||
path = base_dir + "/yaml/"
|
||||
for file in os.listdir(path):
|
||||
if file.endswith(".yaml"):
|
||||
yaml_files_unsorted.append(file)
|
||||
else:
|
||||
print(
|
||||
"Unsupported configuration file type. Please contact Arcolinux Support."
|
||||
)
|
||||
# Need to sort the list (Or do we? I choose to)
|
||||
yaml_files = sorted(yaml_files_unsorted)
|
||||
"""
|
||||
|
||||
# Check github for updated files
|
||||
# fn.check_github(yaml_files)
|
||||
# ==========================================================
|
||||
# GENERATE STACK
|
||||
# ==========================================================
|
||||
stack = Gtk.Stack()
|
||||
# stack.set_transition_type(Gtk.StackTransitionType.SLIDE_UP_DOWN)
|
||||
stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
|
||||
stack.set_transition_duration(350)
|
||||
|
||||
vbox_stack = []
|
||||
stack_item = 0
|
||||
|
||||
# Max Threads
|
||||
"""
|
||||
Fatal Python error: Segmentation fault
|
||||
This error happens randomly, due to the for loop iteration on the cpu_count
|
||||
old code: for x in range(cpu_count()):
|
||||
"""
|
||||
|
||||
# spawn only 1 GUI_Worker threads, as any number greater causes a Segmentation fault
|
||||
|
||||
worker = GUI_Worker(self.queue)
|
||||
worker.name = "thread_GUI_Worker"
|
||||
# Set the worker to be True to allow processing, and avoid Blocking
|
||||
# worker.daemon = True
|
||||
worker.start()
|
||||
|
||||
for category in self.packages:
|
||||
# NOTE: IF the yaml file name standard changes, be sure to update this, or weirdness will follow.
|
||||
|
||||
# this is the side stack listing all categories
|
||||
vbox_stack.append(
|
||||
Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||
)
|
||||
stack.add_titled(
|
||||
vbox_stack[stack_item],
|
||||
str("stack" + str(len(vbox_stack))),
|
||||
category,
|
||||
)
|
||||
|
||||
packages_lst = self.packages[category]
|
||||
|
||||
# Multithreading!
|
||||
self.queue.put(
|
||||
(
|
||||
self,
|
||||
Gtk,
|
||||
vbox_stack[stack_item],
|
||||
category,
|
||||
packages_lst,
|
||||
)
|
||||
)
|
||||
stack_item += 1
|
||||
|
||||
# send a signal that no further items are to be put on the queue
|
||||
self.queue.put(None)
|
||||
# safety to ensure that we finish threading before we continue on.
|
||||
|
||||
self.queue.join()
|
||||
fn.logger.debug("GUI Worker thread completed")
|
||||
|
||||
stack_switcher = Gtk.StackSidebar()
|
||||
stack_switcher.set_name("sidebar")
|
||||
stack_switcher.set_stack(stack)
|
||||
|
||||
# =====================================================
|
||||
# LOGO
|
||||
# =====================================================
|
||||
|
||||
ivbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||
pixbuf = GdkPixbuf.Pixbuf().new_from_file_at_size(
|
||||
os.path.join(base_dir, "images/sofirem.png"), 45, 45
|
||||
)
|
||||
image = Gtk.Image().new_from_pixbuf(pixbuf)
|
||||
|
||||
# remove the focus on startup from search entry
|
||||
ivbox.set_property("can-focus", True)
|
||||
Gtk.Window.grab_focus(ivbox)
|
||||
|
||||
# =====================================================
|
||||
# RECACHE BUTTON
|
||||
# =====================================================
|
||||
|
||||
# btnReCache = Gtk.Button(label="Recache Applications")
|
||||
# btnReCache.connect("clicked", self.recache_clicked)
|
||||
# btnReCache.set_property("has-tooltip", True)
|
||||
# btnReCache.connect("query-tooltip", self.tooltip_callback,
|
||||
# "Refresh the application cache")
|
||||
|
||||
# =====================================================
|
||||
# REPOS
|
||||
# =====================================================
|
||||
|
||||
# =====================================================
|
||||
# QUIT BUTTON
|
||||
# =====================================================
|
||||
btn_quit_app = Gtk.Button(label="Quit")
|
||||
btn_quit_app.set_size_request(100, 30)
|
||||
btn_quit_app.connect("clicked", self.on_close, "delete-event")
|
||||
btn_context = btn_quit_app.get_style_context()
|
||||
btn_context.add_class("destructive-action")
|
||||
# =====================================================
|
||||
# SEARCH BOX
|
||||
# =====================================================
|
||||
self.searchentry = Gtk.SearchEntry()
|
||||
self.searchentry.set_placeholder_text("Search...")
|
||||
self.searchentry.connect("activate", self.on_search_activated)
|
||||
self.searchentry.connect("icon-release", self.on_search_cleared)
|
||||
|
||||
ivsearchbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
|
||||
ivsearchbox.pack_start(self.searchentry, False, False, 0)
|
||||
|
||||
ivbox.pack_start(image, False, False, 0)
|
||||
ivbox.pack_start(ivsearchbox, False, False, 0)
|
||||
ivbox.pack_start(stack_switcher, True, True, 0)
|
||||
ivbox.pack_start(btn_quit_app, False, False, 0)
|
||||
|
||||
vbox1.pack_start(hbox0, False, False, 0)
|
||||
vbox1.pack_start(stack, True, True, 0)
|
||||
|
||||
hbox.pack_start(ivbox, False, True, 0)
|
||||
hbox.pack_start(vbox1, True, True, 0)
|
||||
|
||||
stack.set_hhomogeneous(False)
|
||||
stack.set_vhomogeneous(False)
|
||||
|
||||
if self.search_activated:
|
||||
self.show_all()
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in GUI(): %s" % e)
|
||||
|
||||
|
||||
# setup headerbar including popover settings
|
||||
def setup_headerbar(self, Gtk, settings):
|
||||
try:
|
||||
header_bar_title = "Sofirem"
|
||||
headerbar = Gtk.HeaderBar()
|
||||
headerbar.set_title(header_bar_title)
|
||||
headerbar.set_show_close_button(True)
|
||||
|
||||
self.set_titlebar(headerbar)
|
||||
|
||||
toolbutton = Gtk.ToolButton()
|
||||
# icon-name open-menu-symbolic / open-menu-symbolic.symbolic
|
||||
toolbutton.set_icon_name("open-menu-symbolic")
|
||||
|
||||
toolbutton.connect("clicked", self.on_settings_clicked)
|
||||
|
||||
headerbar.pack_end(toolbutton)
|
||||
|
||||
self.popover = Gtk.Popover()
|
||||
self.popover.set_relative_to(toolbutton)
|
||||
|
||||
vbox = Gtk.Box(spacing=0, orientation=Gtk.Orientation.VERTICAL)
|
||||
vbox.set_border_width(15)
|
||||
|
||||
# switches
|
||||
|
||||
# switch to display package versions
|
||||
self.switch_package_version = Gtk.Switch()
|
||||
|
||||
if settings != None:
|
||||
if settings["Display Package Versions"]:
|
||||
self.display_versions = settings["Display Package Versions"]
|
||||
|
||||
if self.display_versions == True:
|
||||
self.switch_package_version.set_active(True)
|
||||
else:
|
||||
self.switch_package_version.set_active(False)
|
||||
|
||||
self.switch_package_version.connect("notify::active", self.version_toggle)
|
||||
|
||||
# switch to import arcolinux keyring
|
||||
self.switch_arco_keyring = Gtk.Switch()
|
||||
|
||||
if (
|
||||
fn.check_package_installed("arcolinux-keyring") is False
|
||||
or fn.verify_arco_pacman_conf() is False
|
||||
):
|
||||
self.switch_arco_keyring.set_state(False)
|
||||
|
||||
else:
|
||||
self.switch_arco_keyring.set_state(True)
|
||||
|
||||
self.switch_arco_keyring.connect("state-set", self.arco_keyring_toggle)
|
||||
|
||||
# switch to import arcolinix mirrorlist
|
||||
self.switch_arco_mirrorlist = Gtk.Switch()
|
||||
|
||||
if (
|
||||
fn.check_package_installed("arcolinux-mirrorlist-git") is False
|
||||
or fn.verify_arco_pacman_conf() is False
|
||||
):
|
||||
self.switch_arco_mirrorlist.set_state(False)
|
||||
|
||||
else:
|
||||
self.switch_arco_mirrorlist.set_state(True)
|
||||
|
||||
self.switch_arco_mirrorlist.connect("state-set", self.arco_mirrorlist_toggle)
|
||||
|
||||
# switch to display package progress window
|
||||
self.switch_package_progress = Gtk.Switch()
|
||||
|
||||
if settings != None:
|
||||
if settings["Display Package Progress"]:
|
||||
self.display_package_progress = settings["Display Package Progress"]
|
||||
|
||||
if self.display_package_progress == True:
|
||||
self.switch_package_progress.set_active(True)
|
||||
else:
|
||||
self.switch_package_progress.set_active(False)
|
||||
self.switch_package_progress.connect(
|
||||
"notify::active", self.package_progress_toggle
|
||||
)
|
||||
|
||||
# modalbuttons
|
||||
|
||||
# button to open the pacman log monitoring dialog
|
||||
self.modelbtn_pacmanlog = Gtk.ModelButton()
|
||||
self.modelbtn_pacmanlog.connect("clicked", self.on_pacman_log_clicked)
|
||||
self.modelbtn_pacmanlog.set_name("modelbtn_popover")
|
||||
self.modelbtn_pacmanlog.props.centered = False
|
||||
self.modelbtn_pacmanlog.props.text = "Open Pacman Log File"
|
||||
|
||||
# button to display installed packages window
|
||||
modelbtn_packages_export = Gtk.ModelButton()
|
||||
modelbtn_packages_export.connect("clicked", self.on_packages_export_clicked)
|
||||
modelbtn_packages_export.set_name("modelbtn_popover")
|
||||
modelbtn_packages_export.props.centered = False
|
||||
modelbtn_packages_export.props.text = "Show Installed Packages"
|
||||
|
||||
# button to display import packages window
|
||||
modelbtn_packages_import = Gtk.ModelButton()
|
||||
modelbtn_packages_import.connect("clicked", self.on_packages_import_clicked)
|
||||
modelbtn_packages_import.set_name("modelbtn_popover")
|
||||
modelbtn_packages_import.props.centered = False
|
||||
modelbtn_packages_import.props.text = "Import Packages"
|
||||
|
||||
# button to show about dialog
|
||||
modelbtn_about_app = Gtk.ModelButton()
|
||||
modelbtn_about_app.connect("clicked", self.on_about_app_clicked)
|
||||
modelbtn_about_app.set_name("modelbtn_popover")
|
||||
modelbtn_about_app.props.centered = False
|
||||
modelbtn_about_app.props.text = "About Sofirem"
|
||||
|
||||
# button to show iso package lists window
|
||||
modelbtn_iso_packages_list = Gtk.ModelButton()
|
||||
modelbtn_iso_packages_list.connect(
|
||||
"clicked", self.on_arcolinux_iso_packages_clicked
|
||||
)
|
||||
modelbtn_iso_packages_list.set_name("modelbtn_popover")
|
||||
modelbtn_iso_packages_list.props.centered = False
|
||||
modelbtn_iso_packages_list.props.text = "Explore ArcoLinux ISO Packages"
|
||||
|
||||
# button to show package search window
|
||||
modelbtn_package_search = Gtk.ModelButton()
|
||||
modelbtn_package_search.connect("clicked", self.on_package_search_clicked)
|
||||
modelbtn_package_search.set_name("modelbtn_popover")
|
||||
modelbtn_package_search.props.centered = False
|
||||
modelbtn_package_search.props.text = "Open Package Search"
|
||||
|
||||
# grid for the switch options
|
||||
grid_switches = Gtk.Grid()
|
||||
grid_switches.set_row_homogeneous(True)
|
||||
|
||||
lbl_package_version = Gtk.Label(xalign=0)
|
||||
lbl_package_version.set_text("Display Package Versions")
|
||||
|
||||
lbl_package_version_padding = Gtk.Label(xalign=0)
|
||||
lbl_package_version_padding.set_text(" ")
|
||||
|
||||
lbl_package_progress = Gtk.Label(xalign=0)
|
||||
lbl_package_progress.set_text("Display Package Progress")
|
||||
|
||||
lbl_package_progress_padding = Gtk.Label(xalign=0)
|
||||
lbl_package_progress_padding.set_text(" ")
|
||||
|
||||
lbl_arco_keyring = Gtk.Label(xalign=0)
|
||||
lbl_arco_keyring.set_text("Import ArcoLinux Keyring")
|
||||
|
||||
lbl_arco_keyring_padding = Gtk.Label(xalign=0)
|
||||
lbl_arco_keyring_padding.set_text(" ")
|
||||
|
||||
lbl_arco_mirrorlist = Gtk.Label(xalign=0)
|
||||
lbl_arco_mirrorlist.set_text("Import ArcoLinux Mirrorlist")
|
||||
|
||||
lbl_arco_mirrorlist_padding = Gtk.Label(xalign=0)
|
||||
lbl_arco_mirrorlist_padding.set_text(" ")
|
||||
|
||||
grid_switches.attach(lbl_package_version, 0, 1, 1, 1)
|
||||
grid_switches.attach_next_to(
|
||||
lbl_package_version_padding,
|
||||
lbl_package_version,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach_next_to(
|
||||
self.switch_package_version,
|
||||
lbl_package_version_padding,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach(lbl_package_progress, 0, 2, 1, 1)
|
||||
grid_switches.attach_next_to(
|
||||
lbl_package_progress_padding,
|
||||
lbl_package_progress,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach_next_to(
|
||||
self.switch_package_progress,
|
||||
lbl_package_progress_padding,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach(lbl_arco_keyring, 0, 3, 1, 1)
|
||||
grid_switches.attach_next_to(
|
||||
lbl_arco_keyring_padding,
|
||||
lbl_arco_keyring,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach_next_to(
|
||||
self.switch_arco_keyring,
|
||||
lbl_arco_keyring_padding,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach(lbl_arco_mirrorlist, 0, 4, 1, 1)
|
||||
grid_switches.attach_next_to(
|
||||
lbl_arco_mirrorlist_padding,
|
||||
lbl_arco_mirrorlist,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
grid_switches.attach_next_to(
|
||||
self.switch_arco_mirrorlist,
|
||||
lbl_arco_mirrorlist_padding,
|
||||
Gtk.PositionType.RIGHT,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
|
||||
vbox_buttons = Gtk.Box(spacing=1, orientation=Gtk.Orientation.VERTICAL)
|
||||
vbox_buttons.pack_start(self.modelbtn_pacmanlog, False, True, 0)
|
||||
vbox_buttons.pack_start(modelbtn_packages_export, False, True, 0)
|
||||
vbox_buttons.pack_start(modelbtn_packages_import, False, True, 0)
|
||||
vbox_buttons.pack_start(modelbtn_iso_packages_list, False, True, 0)
|
||||
vbox_buttons.pack_start(modelbtn_package_search, False, True, 0)
|
||||
vbox_buttons.pack_start(modelbtn_about_app, False, True, 0)
|
||||
|
||||
vbox.pack_start(grid_switches, False, False, 0)
|
||||
vbox.pack_start(vbox_buttons, False, False, 0)
|
||||
|
||||
self.popover.add(vbox)
|
||||
self.popover.set_position(Gtk.PositionType.BOTTOM)
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in setup_headerbar(): %s" % e)
|
||||
429
usr/share/sofirem/ui/ISOPackagesWindow.py
Normal file
429
usr/share/sofirem/ui/ISOPackagesWindow.py
Normal file
@@ -0,0 +1,429 @@
|
||||
# This class is used to create a window showing a list of packages available for a given ArcoLinux ISO
|
||||
|
||||
import os
|
||||
import gi
|
||||
import requests
|
||||
import Functions as fn
|
||||
from ui.MessageDialog import MessageDialog
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib
|
||||
|
||||
|
||||
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
|
||||
arcolinux_isos = [
|
||||
"arcolinuxs-xanmod-iso",
|
||||
"arcolinuxs-zen-iso",
|
||||
"arcolinuxs-lts-iso",
|
||||
"arcolinuxs-iso",
|
||||
"arcolinuxl-iso",
|
||||
"arcolinuxd-iso",
|
||||
]
|
||||
|
||||
arcolinuxb_isos = [
|
||||
"arco-sway",
|
||||
"arco-plasma",
|
||||
"arco-hyprland",
|
||||
"arco-chadwm",
|
||||
"arco-dusk",
|
||||
"arco-dwm",
|
||||
"arco-berry",
|
||||
"arco-hypr",
|
||||
"arco-enlightenment",
|
||||
"arco-xtended",
|
||||
"arco-pantheon",
|
||||
"arco-awesome",
|
||||
"arco-bspwm",
|
||||
"arco-cinnamon",
|
||||
"arco-budgie",
|
||||
"arco-cutefish",
|
||||
"arco-cwm",
|
||||
"arco-deepin",
|
||||
"arco-gnome",
|
||||
"arco-fvwm3",
|
||||
"arco-herbstluftwm",
|
||||
"arco-i3",
|
||||
"arco-icewm",
|
||||
"arco-jwm",
|
||||
"arco-leftwm",
|
||||
"arco-lxqt",
|
||||
"arco-mate",
|
||||
"arco-openbox",
|
||||
"arco-qtile",
|
||||
"arco-spectrwm",
|
||||
"arco-ukui",
|
||||
"arco-wmderland",
|
||||
"arco-xfce",
|
||||
"arco-xmonad",
|
||||
]
|
||||
|
||||
github_arcolinux_packagelist = "https://raw.githubusercontent.com/${ARCOLINUX}/${ISO}/master/archiso/packages.x86_64"
|
||||
headers = {"Content-Type": "text/plain;charset=UTF-8"}
|
||||
|
||||
|
||||
class ISOPackagesWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
Gtk.Window.__init__(self)
|
||||
|
||||
headerbar = Gtk.HeaderBar()
|
||||
headerbar.set_title("ArcoLinux ISO Package Explorer")
|
||||
headerbar.set_show_close_button(True)
|
||||
|
||||
# remove the focus on startup from search entry
|
||||
headerbar.set_property("can-focus", True)
|
||||
Gtk.Window.grab_focus(headerbar)
|
||||
|
||||
self.set_resizable(True)
|
||||
self.set_size_request(500, 600)
|
||||
self.set_border_width(10)
|
||||
self.set_titlebar(headerbar)
|
||||
self.set_icon_from_file(os.path.join(base_dir, "images/sofirem.png"))
|
||||
self.treeview_loaded = False
|
||||
self.build_gui()
|
||||
|
||||
def get_packagelist(self):
|
||||
try:
|
||||
# make request to get the package list from github
|
||||
url = None
|
||||
|
||||
self.package_list = []
|
||||
|
||||
if "-iso" in self.selected_iso:
|
||||
url = github_arcolinux_packagelist.replace(
|
||||
"${ARCOLINUX}", "arcolinux"
|
||||
).replace("${ISO}", self.selected_iso)
|
||||
github_arcolinux = [
|
||||
"https://github.com/arcolinux/",
|
||||
self.selected_iso,
|
||||
"/blob/master/archiso/packages.x86_64",
|
||||
]
|
||||
|
||||
self.github_source = "".join(github_arcolinux)
|
||||
else:
|
||||
url = github_arcolinux_packagelist.replace(
|
||||
"${ARCOLINUX}", "arcolinuxb"
|
||||
).replace("${ISO}", self.selected_iso)
|
||||
|
||||
github_arcolinuxb = [
|
||||
"https://github.com/arcolinuxb/",
|
||||
self.selected_iso,
|
||||
"/blob/master/archiso/packages.x86_64",
|
||||
]
|
||||
|
||||
self.github_source = "".join(github_arcolinuxb)
|
||||
|
||||
r = requests.get(url, headers=headers, allow_redirects=True)
|
||||
|
||||
# read the package list ignore any commented lines
|
||||
if r.status_code == 200:
|
||||
if len(r.text) > 0:
|
||||
for line in r.text.splitlines():
|
||||
if "#" not in line.strip() and len(line.strip()) > 0:
|
||||
self.package_list.append((line.strip(), None))
|
||||
else:
|
||||
fn.logger.error("Request for %s returned %s" % (url, r.status_code))
|
||||
|
||||
message_dialog = MessageDialog(
|
||||
"Error",
|
||||
"Request failed",
|
||||
"Failed to request package list",
|
||||
"Request for %s returned status code = %s" % (url, r.status_code),
|
||||
"error",
|
||||
True,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
message_dialog.destroy()
|
||||
|
||||
except Exception as e:
|
||||
message_dialog = MessageDialog(
|
||||
"Error",
|
||||
"Request failed",
|
||||
"Failed to request package list",
|
||||
e,
|
||||
"error",
|
||||
True,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
message_dialog.destroy()
|
||||
|
||||
def on_combo_iso_changed(self, combo):
|
||||
try:
|
||||
iso = combo.get_active_text()
|
||||
if iso is not None:
|
||||
self.selected_iso = iso
|
||||
self.get_packagelist()
|
||||
|
||||
if len(self.package_list) > 0:
|
||||
lbl_github_source_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_github_source_title.set_markup("<b>Package list source</b>")
|
||||
|
||||
lbl_github_source_value = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_github_source_value.set_markup(
|
||||
"<a href='%s'>%s</a>" % (self.github_source, self.github_source)
|
||||
)
|
||||
|
||||
lbl_package_count_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_package_count_title.set_markup("<b>Activated packages</b>")
|
||||
|
||||
lbl_package_count_value = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_package_count_value.set_text(str(len(self.package_list)))
|
||||
|
||||
self.filename = "%s/sofirem-exports/%s-%s-packages.x86_64.txt" % (
|
||||
fn.home,
|
||||
self.selected_iso,
|
||||
fn.datetime.now().strftime("%Y-%m-%d"),
|
||||
)
|
||||
|
||||
lbl_export_desc_title = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_export_desc_title.set_markup("<b>Export destination</b>")
|
||||
|
||||
lbl_export_desc_value = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_export_desc_value.set_text(self.filename)
|
||||
|
||||
if self.treeview_loaded is True:
|
||||
self.vbox_package_data.destroy()
|
||||
|
||||
search_entry = Gtk.SearchEntry()
|
||||
search_entry.set_placeholder_text("Search...")
|
||||
search_entry.set_size_request(450, 0)
|
||||
|
||||
grid_package_data = Gtk.Grid()
|
||||
|
||||
treestore_packages_explorer = Gtk.TreeStore(str, str)
|
||||
|
||||
for item in sorted(self.package_list):
|
||||
treestore_packages_explorer.append(None, list(item))
|
||||
|
||||
treeview_packages_explorer = Gtk.TreeView()
|
||||
treeview_packages_explorer.set_search_entry(search_entry)
|
||||
|
||||
treeview_packages_explorer.set_model(treestore_packages_explorer)
|
||||
|
||||
renderer = Gtk.CellRendererText()
|
||||
column = Gtk.TreeViewColumn("Packages", renderer, text=0)
|
||||
|
||||
treeview_packages_explorer.append_column(column)
|
||||
|
||||
path = Gtk.TreePath.new_from_indices([0])
|
||||
|
||||
selection = treeview_packages_explorer.get_selection()
|
||||
|
||||
selection.select_path(path)
|
||||
|
||||
treeview_packages_explorer.expand_all()
|
||||
treeview_packages_explorer.columns_autosize()
|
||||
|
||||
scrolled_window = Gtk.ScrolledWindow()
|
||||
scrolled_window.set_vexpand(True)
|
||||
scrolled_window.set_hexpand(True)
|
||||
|
||||
scrolled_window.add(treeview_packages_explorer)
|
||||
|
||||
grid_treeview = Gtk.Grid()
|
||||
grid_treeview.set_column_homogeneous(True)
|
||||
|
||||
self.vbox_package_data = Gtk.Box(
|
||||
orientation=Gtk.Orientation.VERTICAL, spacing=0
|
||||
)
|
||||
|
||||
self.vbox_package_data.pack_start(
|
||||
lbl_github_source_title, False, True, 1
|
||||
)
|
||||
|
||||
self.vbox_package_data.pack_start(
|
||||
lbl_github_source_value, False, True, 1
|
||||
)
|
||||
|
||||
self.vbox_package_data.pack_start(
|
||||
lbl_package_count_title, False, True, 1
|
||||
)
|
||||
|
||||
self.vbox_package_data.pack_start(
|
||||
lbl_package_count_value, False, True, 1
|
||||
)
|
||||
|
||||
self.vbox_package_data.pack_start(
|
||||
lbl_export_desc_title, False, True, 1
|
||||
)
|
||||
self.vbox_package_data.pack_start(
|
||||
lbl_export_desc_value, False, True, 1
|
||||
)
|
||||
|
||||
lbl_padding_search_entry1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding_search_entry1.set_text("")
|
||||
|
||||
lbl_padding_search_entry2 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding_search_entry2.set_text("")
|
||||
|
||||
grid_search_entry = Gtk.Grid()
|
||||
|
||||
grid_search_entry.attach(lbl_padding_search_entry1, 0, 1, 1, 1)
|
||||
grid_search_entry.attach(search_entry, 0, 2, 1, 1)
|
||||
grid_search_entry.attach(lbl_padding_search_entry2, 0, 3, 1, 1)
|
||||
|
||||
self.vbox_package_data.pack_start(
|
||||
grid_search_entry, False, False, 1
|
||||
)
|
||||
|
||||
self.vbox_package_data.pack_start(scrolled_window, False, True, 1)
|
||||
|
||||
self.vbox_combo.pack_start(self.vbox_package_data, False, True, 1)
|
||||
|
||||
self.show_all()
|
||||
|
||||
self.treeview_loaded = True
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in on_combo_iso_changed(): %s" % e)
|
||||
|
||||
def on_iso_package_list_export(self, widget):
|
||||
# export the package list to a file inside $HOME/sofirem-exports
|
||||
fn.logger.debug("Exporting ArcoLinux ISO package list")
|
||||
try:
|
||||
if self.filename is not None:
|
||||
with open(self.filename, "w", encoding="utf-8") as f:
|
||||
f.write(
|
||||
"# Created by Sofirem on %s\n"
|
||||
% fn.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
f.write("# %s\n" % self.github_source)
|
||||
for line in sorted(self.package_list):
|
||||
f.write("%s\n" % line[0])
|
||||
|
||||
if os.path.exists(self.filename):
|
||||
message_dialog = MessageDialog(
|
||||
"Info",
|
||||
"Package export complete",
|
||||
"Package list exported to %s" % self.filename,
|
||||
"",
|
||||
"info",
|
||||
False,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
else:
|
||||
message_dialog = MessageDialog(
|
||||
"Error",
|
||||
"Package export failed",
|
||||
"Package list export failed",
|
||||
"",
|
||||
"error",
|
||||
False,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
# file is created by root, update the permissions to the sudo username
|
||||
fn.permissions(self.filename)
|
||||
else:
|
||||
message_dialog = MessageDialog(
|
||||
"Warning",
|
||||
"Select an ISO",
|
||||
"An ArcoLinux ISO needs to be selected before exporting",
|
||||
"",
|
||||
"warning",
|
||||
False,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in on_iso_package_list_export(): %s" % e)
|
||||
|
||||
def on_close(self, widget):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
|
||||
def populate_combo_iso(self):
|
||||
for arco_iso in arcolinux_isos:
|
||||
self.combo_iso.append_text(arco_iso)
|
||||
|
||||
for arco_isob in sorted(arcolinuxb_isos):
|
||||
self.combo_iso.append_text(arco_isob)
|
||||
|
||||
def build_gui(self):
|
||||
try:
|
||||
lbl_select_iso = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_select_iso.set_markup("<b>Select ArcoLinux ISO</b>")
|
||||
|
||||
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.combo_iso = Gtk.ComboBoxText()
|
||||
self.combo_iso.set_wrap_width(3)
|
||||
self.combo_iso.set_entry_text_column(0)
|
||||
self.combo_iso.connect("changed", self.on_combo_iso_changed)
|
||||
|
||||
self.populate_combo_iso()
|
||||
|
||||
self.filename = None
|
||||
|
||||
grid_top = Gtk.Grid()
|
||||
|
||||
grid_top.attach(lbl_select_iso, 0, 1, 1, 1)
|
||||
grid_top.attach_next_to(
|
||||
lbl_padding1, lbl_select_iso, Gtk.PositionType.BOTTOM, 1, 1
|
||||
)
|
||||
grid_top.attach(self.combo_iso, 0, 2, 1, 1)
|
||||
grid_top.attach(lbl_padding2, 0, 3, 1, 1)
|
||||
|
||||
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)
|
||||
|
||||
btn_export = Gtk.Button(label="Export")
|
||||
btn_export.set_size_request(100, 30)
|
||||
btn_export.connect("clicked", self.on_iso_package_list_export)
|
||||
btn_export.set_halign(Gtk.Align.END)
|
||||
|
||||
grid_bottom = Gtk.Grid()
|
||||
grid_bottom.attach(btn_ok, 0, 1, 1, 1)
|
||||
|
||||
lbl_padding3 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding3.set_text(" ")
|
||||
|
||||
grid_bottom.attach_next_to(
|
||||
lbl_padding3, btn_ok, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
grid_bottom.attach_next_to(
|
||||
btn_export, lbl_padding3, Gtk.PositionType.RIGHT, 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.vbox_combo = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||
|
||||
self.vbox_combo.pack_start(grid_top, False, True, 0)
|
||||
self.vbox_combo.pack_end(vbox_bottom, False, True, 0)
|
||||
|
||||
self.add(self.vbox_combo)
|
||||
|
||||
self.show_all()
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in build_gui(): %s" % e)
|
||||
118
usr/share/sofirem/ui/MessageDialog.py
Normal file
118
usr/share/sofirem/ui/MessageDialog.py
Normal file
@@ -0,0 +1,118 @@
|
||||
# This class is used to create a modal dialog window showing detailed information about an event
|
||||
|
||||
import os
|
||||
import gi
|
||||
import Functions as fn
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk
|
||||
|
||||
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
# base_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
class MessageDialog(Gtk.Dialog):
|
||||
# message_type is a string, either one of "info", "warning", "error" to show which infobar to display
|
||||
# extended argument when set to true shows a textview inside the dialog
|
||||
# extended argument when set to false only shows a standard dialog
|
||||
def __init__(
|
||||
self, title, subtitle, first_msg, secondary_msg, message_type, extended
|
||||
):
|
||||
Gtk.Dialog.__init__(self)
|
||||
|
||||
headerbar = Gtk.HeaderBar()
|
||||
headerbar.set_title(title)
|
||||
headerbar.set_show_close_button(True)
|
||||
|
||||
self.set_resizable(True)
|
||||
|
||||
self.set_border_width(10)
|
||||
|
||||
self.set_titlebar(headerbar)
|
||||
|
||||
btn_ok = Gtk.Button(label="OK")
|
||||
btn_ok.set_size_request(100, 30)
|
||||
btn_ok.connect("clicked", on_message_dialog_ok_response, self)
|
||||
btn_ok.set_halign(Gtk.Align.END)
|
||||
self.set_icon_from_file(os.path.join(base_dir, "images/sofirem.png"))
|
||||
|
||||
infobar = Gtk.InfoBar()
|
||||
|
||||
if message_type == "info":
|
||||
infobar.set_name("infobar_info")
|
||||
if message_type == "error":
|
||||
infobar.set_name("infobar_error")
|
||||
if message_type == "warning":
|
||||
infobar.set_name("infobar_warning")
|
||||
|
||||
lbl_title_message = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_title_message.set_markup("<b>%s</b>" % subtitle)
|
||||
content = infobar.get_content_area()
|
||||
content.add(lbl_title_message)
|
||||
|
||||
infobar.set_revealed(True)
|
||||
|
||||
lbl_padding1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding1.set_text("")
|
||||
|
||||
lbl_padding2 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding2.set_text("")
|
||||
|
||||
grid_message = Gtk.Grid()
|
||||
|
||||
grid_message.attach(infobar, 0, 0, 1, 1)
|
||||
grid_message.attach(lbl_padding1, 0, 1, 1, 1)
|
||||
|
||||
if extended is True:
|
||||
scrolled_window = Gtk.ScrolledWindow()
|
||||
textview = Gtk.TextView()
|
||||
textview.set_property("editable", False)
|
||||
textview.set_property("monospace", True)
|
||||
textview.set_border_width(10)
|
||||
textview.set_vexpand(True)
|
||||
textview.set_hexpand(True)
|
||||
|
||||
msg_buffer = textview.get_buffer()
|
||||
msg_buffer.insert(
|
||||
msg_buffer.get_end_iter(),
|
||||
"Event timestamp = %s\n"
|
||||
% fn.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
)
|
||||
msg_buffer.insert(msg_buffer.get_end_iter(), "%s\n" % first_msg)
|
||||
msg_buffer.insert(msg_buffer.get_end_iter(), "%s\n" % secondary_msg)
|
||||
|
||||
# move focus away from the textview, to hide the cursor at load
|
||||
headerbar.set_property("can-focus", True)
|
||||
Gtk.Window.grab_focus(headerbar)
|
||||
|
||||
scrolled_window.add(textview)
|
||||
|
||||
grid_message.attach(scrolled_window, 0, 2, 1, 1)
|
||||
grid_message.attach(lbl_padding2, 0, 3, 1, 1)
|
||||
|
||||
self.set_default_size(800, 600)
|
||||
|
||||
else:
|
||||
# do not display textview
|
||||
lbl_first_message = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_first_message.set_text(first_msg)
|
||||
|
||||
lbl_second_message = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_second_message.set_markup("<b>%s</b>" % secondary_msg)
|
||||
|
||||
grid_message.attach(lbl_first_message, 0, 2, 1, 1)
|
||||
grid_message.attach(lbl_second_message, 0, 3, 1, 1)
|
||||
|
||||
self.set_default_size(600, 100)
|
||||
self.set_resizable(False)
|
||||
|
||||
vbox_close = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
vbox_close.pack_start(btn_ok, True, True, 1)
|
||||
|
||||
self.vbox.add(grid_message)
|
||||
self.vbox.add(vbox_close)
|
||||
|
||||
|
||||
def on_message_dialog_ok_response(self, widget):
|
||||
# widget.hide()
|
||||
widget.destroy()
|
||||
283
usr/share/sofirem/ui/PackageListDialog.py
Normal file
283
usr/share/sofirem/ui/PackageListDialog.py
Normal file
@@ -0,0 +1,283 @@
|
||||
# This class is used to create a modal dialog window to display currently installed packages
|
||||
|
||||
import os
|
||||
import gi
|
||||
import Functions as fn
|
||||
from ui.MessageDialog import MessageDialog
|
||||
from queue import Queue
|
||||
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 PackageListDialog(Gtk.Dialog):
|
||||
def __init__(self):
|
||||
Gtk.Dialog.__init__(self)
|
||||
|
||||
# Create a queue for storing package list exports to display inside PackageListDialog
|
||||
self.pkg_export_queue = Queue()
|
||||
|
||||
self.filename = "%s/packages-x86_64.txt" % (fn.export_dir,)
|
||||
|
||||
self.set_resizable(True)
|
||||
self.set_size_request(1050, 700)
|
||||
self.set_modal(True)
|
||||
|
||||
self.set_border_width(10)
|
||||
self.set_icon_from_file(os.path.join(base_dir, "images/sofirem.png"))
|
||||
|
||||
self.connect("delete-event", self.on_close)
|
||||
|
||||
self.installed_packages_list = None
|
||||
|
||||
self.headerbar = Gtk.HeaderBar()
|
||||
self.headerbar.set_title("Loading please wait ..")
|
||||
self.headerbar.set_show_close_button(True)
|
||||
|
||||
self.set_titlebar(self.headerbar)
|
||||
|
||||
self.grid_packageslst = Gtk.Grid()
|
||||
self.grid_packageslst.set_column_homogeneous(True)
|
||||
|
||||
self.lbl_info = Gtk.Label(xalign=0, yalign=0)
|
||||
self.lbl_info.set_text("Export destination %s" % self.filename)
|
||||
|
||||
# get a list of installed packages on the system
|
||||
|
||||
self.pacman_export_cmd = ["pacman", "-Qien"]
|
||||
|
||||
fn.Thread(
|
||||
target=fn.get_installed_package_data,
|
||||
args=(self,),
|
||||
daemon=True,
|
||||
).start()
|
||||
|
||||
fn.Thread(target=self.check_queue, daemon=True).start()
|
||||
|
||||
def setup_gui(self):
|
||||
if len(self.installed_packages_list) > 0:
|
||||
self.set_title(
|
||||
"Showing %s installed packages" % len(self.installed_packages_list)
|
||||
)
|
||||
|
||||
search_entry = Gtk.SearchEntry()
|
||||
search_entry.set_placeholder_text("Search...")
|
||||
|
||||
# remove the focus on startup from search entry
|
||||
self.headerbar.set_property("can-focus", True)
|
||||
Gtk.Window.grab_focus(self.headerbar)
|
||||
|
||||
treestore_packages = Gtk.TreeStore(str, str, str, str, str)
|
||||
for item in sorted(self.installed_packages_list):
|
||||
treestore_packages.append(None, list(item))
|
||||
|
||||
treeview_packages = Gtk.TreeView()
|
||||
treeview_packages.set_search_entry(search_entry)
|
||||
|
||||
treeview_packages.set_model(treestore_packages)
|
||||
|
||||
for i, col_title in enumerate(
|
||||
[
|
||||
"Name",
|
||||
"Installed Version",
|
||||
"Latest Version",
|
||||
"Installed Size",
|
||||
"Installed Date",
|
||||
]
|
||||
):
|
||||
renderer = Gtk.CellRendererText()
|
||||
col = Gtk.TreeViewColumn(col_title, renderer, text=i)
|
||||
treeview_packages.append_column(col)
|
||||
|
||||
# allow sorting by installed date
|
||||
|
||||
col_installed_date = treeview_packages.get_column(4)
|
||||
col_installed_date.set_sort_column_id(4)
|
||||
|
||||
treestore_packages.set_sort_func(4, self.compare_install_date, None)
|
||||
|
||||
path = Gtk.TreePath.new_from_indices([0])
|
||||
|
||||
selection = treeview_packages.get_selection()
|
||||
selection.select_path(path)
|
||||
|
||||
treeview_packages.expand_all()
|
||||
treeview_packages.columns_autosize()
|
||||
|
||||
scrolled_window = Gtk.ScrolledWindow()
|
||||
scrolled_window.set_vexpand(True)
|
||||
scrolled_window.set_hexpand(True)
|
||||
|
||||
self.grid_packageslst.attach(scrolled_window, 0, 0, 8, 10)
|
||||
|
||||
lbl_padding1 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding1.set_text("")
|
||||
|
||||
self.grid_packageslst.attach_next_to(
|
||||
lbl_padding1, scrolled_window, Gtk.PositionType.BOTTOM, 1, 1
|
||||
)
|
||||
|
||||
btn_dialog_export = Gtk.Button(label="Export")
|
||||
btn_dialog_export.connect("clicked", self.on_dialog_export_clicked)
|
||||
btn_dialog_export.set_size_request(100, 30)
|
||||
btn_dialog_export.set_halign(Gtk.Align.END)
|
||||
|
||||
btn_dialog_export_close = Gtk.Button(label="Close")
|
||||
btn_dialog_export_close.connect("clicked", self.on_close, "delete-event")
|
||||
btn_dialog_export_close.set_size_request(100, 30)
|
||||
btn_dialog_export_close.set_halign(Gtk.Align.END)
|
||||
|
||||
scrolled_window.add(treeview_packages)
|
||||
|
||||
grid_btn = Gtk.Grid()
|
||||
grid_btn.attach(btn_dialog_export, 0, 1, 1, 1)
|
||||
|
||||
lbl_padding2 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding2.set_text(" ")
|
||||
|
||||
grid_btn.attach_next_to(
|
||||
lbl_padding2, btn_dialog_export, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
grid_btn.attach_next_to(
|
||||
btn_dialog_export_close, lbl_padding2, Gtk.PositionType.RIGHT, 1, 1
|
||||
)
|
||||
|
||||
grid_btn.set_halign(Gtk.Align.END)
|
||||
|
||||
vbox_btn = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
vbox_btn.pack_start(grid_btn, True, True, 1)
|
||||
|
||||
lbl_padding3 = Gtk.Label(xalign=0, yalign=0)
|
||||
lbl_padding3.set_text("")
|
||||
|
||||
self.vbox.add(search_entry)
|
||||
self.vbox.add(lbl_padding3)
|
||||
self.vbox.add(self.grid_packageslst)
|
||||
self.vbox.add(self.lbl_info)
|
||||
self.vbox.add(vbox_btn)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def check_queue(self):
|
||||
while True:
|
||||
self.installed_packages_list = self.pkg_export_queue.get()
|
||||
|
||||
if self.installed_packages_list is not None:
|
||||
break
|
||||
|
||||
self.pkg_export_queue.task_done()
|
||||
|
||||
GLib.idle_add(self.setup_gui, priority=GLib.PRIORITY_DEFAULT)
|
||||
|
||||
def on_close(self, dialog, event):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
|
||||
def on_dialog_export_clicked(self, dialog):
|
||||
try:
|
||||
if not os.path.exists(fn.export_dir):
|
||||
fn.makedirs(fn.export_dir)
|
||||
fn.permissions(fn.export_dir)
|
||||
|
||||
with open(self.filename, "w", encoding="utf-8") as f:
|
||||
f.write(
|
||||
"# This file was auto-generated by Sofirem on %s at %s\n"
|
||||
% (
|
||||
fn.datetime.today().date(),
|
||||
fn.datetime.now().strftime("%H:%M:%S"),
|
||||
)
|
||||
)
|
||||
|
||||
f.write(
|
||||
"# Exported explicitly installed packages using %s\n"
|
||||
% " ".join(self.pacman_export_cmd)
|
||||
)
|
||||
|
||||
for package in sorted(self.installed_packages_list):
|
||||
f.write("%s\n" % (package[0]))
|
||||
|
||||
if os.path.exists(self.filename):
|
||||
fn.logger.info("Export completed")
|
||||
|
||||
# fix permissions, file is owned by root
|
||||
fn.permissions(self.filename)
|
||||
|
||||
message_dialog = MessageDialog(
|
||||
"Info",
|
||||
"Package export complete",
|
||||
"Package list exported to %s" % self.filename,
|
||||
"",
|
||||
"info",
|
||||
False,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
message_dialog.destroy()
|
||||
|
||||
else:
|
||||
fn.logger.error("Export failed")
|
||||
|
||||
message_dialog = MessageDialog(
|
||||
"Error",
|
||||
"Package export failed",
|
||||
"Failed to export package list to %s." % self.filename,
|
||||
"",
|
||||
"error",
|
||||
False,
|
||||
)
|
||||
|
||||
message_dialog.show_all()
|
||||
message_dialog.run()
|
||||
message_dialog.hide()
|
||||
message_dialog.destroy()
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in on_dialog_export_clicked(): %s" % e)
|
||||
|
||||
# noqa: any locales other than en_GB.UTF-8 / en_US.UTF-8 are untested
|
||||
def compare_install_date(self, model, row1, row2, user_data):
|
||||
try:
|
||||
sort_column, _ = model.get_sort_column_id()
|
||||
str_value1 = model.get_value(row1, sort_column)
|
||||
str_value2 = model.get_value(row2, sort_column)
|
||||
|
||||
datetime_value1 = None
|
||||
datetime_value2 = None
|
||||
|
||||
# convert string into datetime object, check if time format is 12H format with AM/PM
|
||||
if str_value1.lower().find("am") > 0 or str_value1.lower().find("pm") > 0:
|
||||
# 12H format
|
||||
datetime_value1 = fn.datetime.strptime(
|
||||
str_value1, "%a %d %b %Y %I:%M:%S %p %Z"
|
||||
).replace(tzinfo=None)
|
||||
datetime_value2 = fn.datetime.strptime(
|
||||
str_value2, "%a %d %b %Y %I:%M:%S %p %Z"
|
||||
).replace(tzinfo=None)
|
||||
else:
|
||||
# 24H format
|
||||
datetime_value1 = fn.datetime.strptime(
|
||||
str_value1, "%a %d %b %Y %H:%M:%S %Z"
|
||||
).replace(tzinfo=None)
|
||||
datetime_value2 = fn.datetime.strptime(
|
||||
str_value2, "%a %d %b %Y %H:%M:%S %Z"
|
||||
).replace(tzinfo=None)
|
||||
|
||||
if datetime_value1 is not None and datetime_value2 is not None:
|
||||
if datetime_value1 < datetime_value2:
|
||||
return -1
|
||||
elif datetime_value1 == datetime_value2:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
except ValueError as ve:
|
||||
# fn.logger.error("ValueError in compare_install_date: %s" % ve)
|
||||
# compare fails due to the format of the datetime string, which hasn't been tested
|
||||
pass
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in compare_install_date: %s" % e)
|
||||
543
usr/share/sofirem/ui/PackageSearchWindow.py
Normal file
543
usr/share/sofirem/ui/PackageSearchWindow.py
Normal file
@@ -0,0 +1,543 @@
|
||||
# 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/sofirem.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)
|
||||
228
usr/share/sofirem/ui/PackagesImportDialog.py
Normal file
228
usr/share/sofirem/ui/PackagesImportDialog.py
Normal file
@@ -0,0 +1,228 @@
|
||||
# ============================================================
|
||||
# Authors: Brad Heffernan - Erik Dubois - Cameron Percival
|
||||
# ============================================================
|
||||
|
||||
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/sofirem.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
|
||||
# self.packages_list = ["cheese", "firefox", "sofirem-dev-git", "sofirem-git"]
|
||||
|
||||
# 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()
|
||||
71
usr/share/sofirem/ui/PacmanLogWindow.py
Normal file
71
usr/share/sofirem/ui/PacmanLogWindow.py
Normal 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("Sofirem - 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/sofirem.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()
|
||||
87
usr/share/sofirem/ui/ProgressBarWindow.py
Normal file
87
usr/share/sofirem/ui/ProgressBarWindow.py
Normal 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
|
||||
400
usr/share/sofirem/ui/ProgressDialog.py
Normal file
400
usr/share/sofirem/ui/ProgressDialog.py
Normal 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("Sofirem - installing package %s" % package.name)
|
||||
|
||||
elif action == "uninstall":
|
||||
self.set_title("Sofirem - 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/sofirem.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()
|
||||
30
usr/share/sofirem/ui/SplashScreen.py
Normal file
30
usr/share/sofirem/ui/SplashScreen.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import gi
|
||||
from Functions import os
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GdkPixbuf, Gdk # noqa
|
||||
|
||||
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
# base_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
class SplashScreen(Gtk.Window):
|
||||
def __init__(self):
|
||||
Gtk.Window.__init__(self, Gtk.WindowType.POPUP, title="")
|
||||
self.set_decorated(False)
|
||||
self.set_resizable(False)
|
||||
self.set_size_request(600, 400)
|
||||
self.set_position(Gtk.WindowPosition.CENTER)
|
||||
|
||||
main_vbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=1)
|
||||
self.add(main_vbox)
|
||||
|
||||
self.image = Gtk.Image()
|
||||
pimage = GdkPixbuf.Pixbuf().new_from_file_at_size(
|
||||
base_dir + "/images/splash.png", 600, 400
|
||||
)
|
||||
self.image.set_from_pixbuf(pimage)
|
||||
|
||||
main_vbox.pack_start(self.image, True, True, 0)
|
||||
|
||||
self.show_all()
|
||||
Reference in New Issue
Block a user