#!/usr/bin/python
##===========================##
## ARCH UPGRADING MANAGER ##
## ver.1.0 ##
##===========================##
## GTK3+ APPLICATION ##
## in python3 ##
##===========================##
## requires: python3, ##
## python-gobject ##
## gtk3 ##
##===========================##
## by Rebellion ##
##===========================##
module_error = ''
libnames = ['gi',
'os',
'socket',
'urllib.request',
'json',
'hashlib',
'getpass',
'threading',
'time',
'sys',
'pathlib',
'bs4']
for libname in libnames:
try:
lib = __import__(libname)
except ImportError as error:
module_error = module_error + ' ==>' + str(error) + '\n'
else:
globals()[libname] = lib
if module_error != '':
print (module_error)
os.system('notify-send -i dialog-warning -u critical \"Arch Update Manager\" \"\n<b>WARNING:</b>\n<i>%s</i>\"'% module_error)
exit(0)
import urllib.request
from pathlib import Path
gi.require_version('Gtk', '3.0')
gi.require_version('Vte', '2.91')
from gi.repository import Gtk,Gdk,GLib,GdkPixbuf,Vte
from bs4 import BeautifulSoup
script = sys.argv[0]
if os.popen('ps aux | grep \"[%s]%s\"'% (script[:1], script[1:])).read().count(script) > 1: exit(0)
user = getpass.getuser()
me_path = os.path.dirname(os.path.abspath(__file__))
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_icon_name('system-software-install')
self.set_border_width(10)
self.set_resizable(False)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_name('window-self')
self.headerbar = Gtk.HeaderBar()
titlebar = Gtk.Label()
titlebar.set_markup('\n<big><b>Arch Updating Manager</b></big>\n')
self.headerbar.set_custom_title(titlebar)
window_close = Gtk.Button.new_from_icon_name('dialog-error-symbolic', Gtk.IconSize.LARGE_TOOLBAR)
window_close.set_name('exit')
info_warning = Gtk.Button.new_from_icon_name('dialog-warning-symbolic', Gtk.IconSize.LARGE_TOOLBAR)
info_warning.set_name('info')
boxExit = Gtk.VBox()
boxExit.pack_start(window_close,True,False,0)
boxInfo = Gtk.VBox()
boxInfo.pack_start(info_warning,True,False,0)
hboxExitInfo = Gtk.HBox(spacing=5)
hboxExitInfo.pack_start(boxInfo,False,False,0)
hboxExitInfo.pack_start(boxExit,False,False,10)
self.headerbar.pack_end(hboxExitInfo)
self.set_titlebar(self.headerbar)
self.spinner = Gtk.Spinner()
global hand_cursor
hand_cursor = Gdk.Cursor(Gdk.CursorType.HAND2)
def on_switch_activated(self, widget):
if switch1.get_active():
combobox.set_sensitive(True)
numbers.set_markup("<b>Old version number kept</b>")
else:
combobox.set_sensitive(False)
numbers.set_markup("")
if switch1.get_active() or switch2.get_active():
if apply_button.get_sensitive() == False: apply_button.set_sensitive(True)
else:
if apply_button.get_sensitive() == True: apply_button.set_sensitive(False)
def tooltip_info(self, widget):
if switch3.get_active():
ii = 0
for package in listbox.get_children():
package.set_has_tooltip(True)
package.set_tooltip_text(items_pacman_info[ii].rstrip())
ii += 1
ii = 0
for package_aur in listbox_aur.get_children():
package_aur.set_has_tooltip(True)
package_aur.set_tooltip_text(items_aur_info[ii].rstrip())
ii += 1
else:
for package in listbox.get_children():
package.set_has_tooltip(False)
package.set_tooltip_text('')
for package_aur in listbox_aur.get_children():
package_aur.set_has_tooltip(False)
package_aur.set_tooltip_text('')
def pkgbuild_infos_glib():
if self.swin2.get_child(): self.swin2.remove(self.swin2.get_child())
return False
def pkgbuild_info(self, widget):
GLib.idle_add(pkgbuild_infos_glib)
def apply_function(_, manager):
if len(pacman_array) == 0 and len(aur_array) == 0 and switch1.get_active() == False and switch2.get_active() == False and manager == '': return
def destroy_window(_):
apply_window.destroy()
def entry_text(_):
thread = threading.Thread(target=entry_text_thread)
thread.daemon = True
thread.start()
def show_command(arg):
def destroy_window_refresh(_):
refresh_button.clicked()
apply_window.destroy()
def endOfCommand(_):
previous_button.set_always_show_image(True)
if arg == '': previous_button.set_label('back and\n refresh')
previous_button.show()
previous_button.set_sensitive(True)
close_button.set_sensitive(True)
close_button.show()
if arg == '':
previous_button.disconnect(previous_button_id)
previous_button.connect('clicked', destroy_window_refresh)
vteTerminal.disconnect(id_vteTerminal_EOF)
filePath = '%s/passwd.sh'% me_path
if os.path.exists(filePath): os.remove(filePath)
apply_window.set_default_size(1000,700)
previous_button.hide()
previous_button.set_sensitive(False)
close_button.hide()
close_button.set_sensitive(False)
textview_scrollable = Gtk.ScrolledWindow()
textview_scrollable.set_border_width(10)
if arg == '':
vbox_passwd.destroy()
label_password_check.destroy()
packages = ' '.join(pacman_array_sorted)
cmd = ''
if arg != 'remove':
try:
socket.create_connection(("
www.google.com", 80))
if arg != 'install':
if len(pacman_array) > 0: cmd = cmd + 'echo \"::PACMAN Updating::\" ; SUDO_ASKPASS=%s/passwd.sh sudo -A pacman -Syu %s ; echo \"::PACMAN Updating ==> finished::\" ; echo ; sudo -k ; '% (me_path,packages)
if len(aur_array) > 0:
bash_array = '('
for i in aur_array:
bash_array = bash_array + ' \"' + i + '\"'
bash_array = bash_array + ' )'
cmd = cmd + 'echo \"::AUR Updating::\" ; packs=%s ; targz=\".tar.gz\" ; old=\"-old\" ; for pack in \"${packs[@]}\" ; do echo \"*** $pack ***\"; [[ -d \"/home/$USER/.cache/AUR/$pack\" ]] && mv /home/$USER/.cache/AUR/$pack /home/$USER/.cache/AUR/$pack$old ; check=\"$pack upgraded!\" ; if ! wget -P /home/$USER/.cache/AUR
https://aur.archlinux.org/cgit/aur.git/snapshot/$pack$targz ; then check=\"download failure!\" ; else tar -xvzf /home/$USER/.cache/AUR/$pack$targz -C /home/$USER/.cache/AUR ; cd /home/$USER/.cache/AUR/$pack ; if ! makepkg -s ; then check=\"makepkg error!\" ; else pack_pkg=$(find /home/$USER/.cache/AUR/$pack -type f -name \"$pack*\" | grep \"pkg.tar.xz\") ; echo ; echo \"consulting new PKGBUILD:\" ; echo \"**********\" ; cat /home/$USER/.cache/AUR/$pack/PKGBUILD ; echo \"**********\" ; if ! SUDO_ASKPASS=%s/passwd.sh sudo -A pacman -U $pack_pkg ; then check=\"installation aborted!\" ; else echo \"cleaning up $pack directory.\" ; if [ -d \"/home/$USER/.cache/AUR/$pack$old\" ] ; then [[ -d \"/home/$USER/.cache/AUR/$pack$old/PKG\" ]] || mkdir /home/$USER/.cache/AUR/$pack$old/PKG ; [[ -d \"/home/$USER/.cache/AUR/$pack$old\" ]] && mv /home/$USER/.cache/AUR/$pack$old/*.pkg.tar.xz /home/$USER/.cache/AUR/$pack$old/PKG/ ; fi ; find /home/$USER/.cache/AUR/$pack/ -type f ! -name ${pack_pkg##*/} -exec rm {} + ; if [ $(find /home/$USER/.cache/AUR/$pack/ -maxdepth 1 -type d | wc -l) -ge 2 ] ; then rm -R -- /home/$USER/.cache/AUR/$pack/*/ ; fi ; mv /home/$USER/.cache/AUR/$pack$targz /home/$USER/.cache/AUR/$pack ; [[ -d /home/$USER/.cache/AUR/$pack$old/PKG ]] && mv /home/$USER/.cache/AUR/$pack$old/PKG /home/$USER/.cache/AUR/$pack/ ; [[ -d /home/$USER/.cache/AUR/$pack$old ]] && rm -rf /home/$USER/.cache/AUR/$pack$old ; fi ; fi ; fi ; echo $check ; if [ \"$check\" != \"$pack upgraded!\" ] ; then [[ -f /home/$USER/.cache/AUR/$pack$targz ]] && rm /home/$USER/.cache/AUR/$pack$targz ; [[ -d /home/$USER/.cache/AUR/$pack ]] && rm -rf /home/$USER/.cache/AUR/$pack ; [[ -d /home/$USER/.cache/AUR/$pack$old ]] && mv /home/$USER/.cache/AUR/$pack$old /home/$USER/.cache/AUR/$pack ; fi ; echo ; done ; echo \"::AUR Updating ==> finished::\" ; echo ; '% (bash_array,me_path)
if switch1.get_active(): cmd = cmd + 'echo \"::Removing Cache::\" ; echo %s | sudo -Sk paccache -rk%s --nocolor ; echo \"::Removing Cache ==> finished::\" ; echo ; '% (psswd,combobox.get_active())
if switch2.get_active(): cmd = cmd + 'echo \"::Removing Orphans::\" ; SUDO_ASKPASS=%s/passwd.sh sudo -A pacman -R $(pacman -Qdtq) ; echo \"::Removing Orphans ==> finished::\" ; echo ; sudo -k ; '% me_path
os.system('echo \"#!/bin/bash\" > %s/passwd.sh ; echo \"echo %s\" >> %s/passwd.sh ; chmod u+x %s/passwd.sh'% (me_path,psswd,me_path,me_path))
else:
cmd = 'tput smul ; echo \"::INSTALLING package::\" ; tput rmul ; echo ; echo ; pack=\"\" ; xmodmap -e \"keycode 65 = \" ; xmodmap -e \"keycode 23 = \" ; while [ \"$pack\" = \"\" ] ; do tput cuu1 ; tput el ; echo -n \"Package to install: \" ; tput bold; read pack ; done ; tput sgr0 ; xmodmap -e \"keycode 65 = space\" ; xmodmap -e \"keycode 23 = Tab\" ; echo ; if pacman -Si $pack ; then pacman -S $pack ; else pacmaur -i $pack ; fi ; '
cmd = 'export HISTCONTROL=ignorespace\n printf \"\\033c\" ; ' + cmd + 'echo ; echo \"** End Of Operations **\" ; exit\n'
except OSError:
cmd = 'printf \"\\033c\" ; echo internet connection failed! ; exit\n'
else:
cmd = 'tput smul ; echo \"::REMOVING package::\" ; tput rmul ; echo ; echo ; pack=\"\" ; xmodmap -e \"keycode 65 = \" ; xmodmap -e \"keycode 23 = \" ; while [ \"$pack\" = \"\" ] ; do tput cuu1 ; tput el ; echo -n \"Package to remove: \" ; tput bold ; read pack ; done ; tput sgr0 ; xmodmap -e \"keycode 65 = space\" ; xmodmap -e \"keycode 23 = Tab\" ; if pacman -Qqm | grep -w $pack ; then echo ; echo \"$pack in AUR: removing and cleaning up cache directory if present..\" ; sudo pacman -R $pack ; [[ -d \"/home/$USER/.cache/AUR/$pack\" ]] && rm -rf /home/$USER/.cache/AUR/$pack ; echo \"done.\" ; elif pacman -Qi $pack ; then echo ; read -p \"Removing deps? -y/n- \" reply ; if [ $reply = \"y\" ] ; then sudo pacman -Rs $pack ; else sudo pacman -R $pack ; fi ; else echo ; echo \"$pack not installed!\" ; fi ; '
cmd = 'export HISTCONTROL=ignorespace\n printf \"\\033c\" ; ' + cmd + 'echo ; echo \"** End Of Operations **\" ; exit\n'
vteTerminal = Vte.Terminal()
vteTerminal.spawn_sync(
Vte.PtyFlags.DEFAULT,
os.environ['HOME'],
["/bin/bash"],
[],
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
None,
None,
)
textview_scrollable.add(vteTerminal)
commands = bytes('stty echo ; '+cmd, encoding = 'utf-8')
apply_vbox.pack_start(textview_scrollable,True,True,10)
textview_scrollable.show_all()
vteTerminal.feed_child(b'stty -echo\n')
vteTerminal.feed_child(commands)
id_vteTerminal_EOF = vteTerminal.connect('eof', endOfCommand)
def gui_update_thread():
label_password_check.show()
password.set_sensitive(False)
def entry_text_thread():
GLib.idle_add(gui_update_thread)
global psswd
psswd = password.get_text()
if os.system('echo %s | sudo -Sk cat /etc/shadow'% psswd) == 256:
label_password_check.set_markup('<span color=\'red\'><b>password incorrect!</b></span>')
password.set_text('')
password.set_sensitive(True)
return
else:
GLib.idle_add(show_command, '')
def spinning_password(self, widget):
if password.get_sensitive(): spinner_password.stop()
else: spinner_password.start()
pacman_array_sorted = sorted(pacman_array, key=str.lower)
apply_window = Gtk.Window().new(Gtk.WindowType.TOPLEVEL)
apply_window.set_urgency_hint(True)
apply_window.set_decorated(False)
apply_window.set_modal(True)
apply_window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
apply_window.set_transient_for(self)
apply_window.set_deletable(True)
apply_window.set_default_size(800,500)
apply_window.set_resizable(False)
apply_window.set_border_width(0)
apply_vbox = Gtk.VBox()
apply_headerbar = Gtk.HeaderBar()
titlebar_apply = Gtk.Label()
titlebar_apply.set_markup('\n<b><big>Arch Updating Manager</big></b>\n apply window\n')
apply_headerbar.set_custom_title(titlebar_apply)
previous_button = Gtk.Button().new_with_label('Going back')
previous_button_id = previous_button.connect('clicked', destroy_window)
previous_button.connect('enter-notify-event', cursorHandOn, '')
previous_button.connect('leave-notify-event', cursorHandOff)
previous_button.set_name('previous')
close_button = Gtk.Button().new_with_label('Close app')
close_button.connect('clicked', Gtk.main_quit)
close_button.connect('enter-notify-event', cursorHandOn, '')
close_button.connect('leave-notify-event', cursorHandOff)
close_button.set_name('close')
apply_headerbar.pack_start(previous_button)
apply_headerbar.pack_end(close_button)
apply_vbox.pack_start(apply_headerbar,False,False,0)
if manager == '':
vbox_passwd = Gtk.VBox(homogeneous=False,spacing=15)
vbox_passwd.set_border_width(50)
apply_window.add(apply_vbox)
if manager == '':
hbox_label = Gtk.HBox(homogeneous=False,spacing=10)
image_label = Gtk.Image.new_from_icon_name('dialog-password-symbolic', Gtk.IconSize.DIALOG)
label_passwd = Gtk.Label()
label_passwd.set_markup('\n\n<b>Authentication Required\n\nAuthentication is required to run Arch Updating Manager</b>\n')
hbox_label.pack_start(image_label,False,False,0)
hbox_label.pack_start(label_passwd,False,False,0)
vbox_passwd.pack_start(hbox_label,False,False,0)
hbox_password = Gtk.HBox(homogeneous=False,spacing=5)
hbox_password.set_border_width(50)
label_password = Gtk.Label()
label_password.set_markup('<b> Password: </b>')
password = Gtk.Entry()
password.set_visibility(False)
password.set_placeholder_text('root password here')
password.connect('activate', entry_text)
password.connect('state-changed', spinning_password)
label_password_check = Gtk.Label()
label_password_check.set_text('checking password')
spinner_password = Gtk.Spinner()
hbox_password.pack_start(label_password,False,False,0)
hbox_password.pack_start(spinner_password,False,False,0)
hbox_password.pack_start(password,True,True,0)
vbox_passwd.pack_start(hbox_password,False,False,0)
apply_vbox.pack_start(vbox_passwd,False,False,0)
apply_vbox.pack_start(label_password_check,False,False,40)
apply_window.show_all()
if manager == '': label_password_check.hide()
else: show_command(manager)
def exitFunctionFadingOut():
self.set_opacity(self.get_opacity() - 0.01)
if self.get_opacity() == 0:
Gtk.main_quit()
return False
else:
return True
def exit_function(self,widget):
GLib.timeout_add(5, exitFunctionFadingOut)
def change_mode():
if self.swin.get_child(): listbox.set_selection_mode(2)
if self.swin1.get_child(): listbox_aur.set_selection_mode(2)
return False
def on_changed_page(notebook, tab, index):
if index == 0:
if self.swin.get_child(): listbox.set_selection_mode(0)
if self.swin1.get_child(): listbox_aur.set_selection_mode(0)
GLib.idle_add(change_mode)
def show_listboxes():
self.swin.add(listbox)
listbox.show_all()
self.swin1.add(listbox_aur)
listbox_aur.show_all()
self.set_sensitive(True)
return False
def cursorHandOn(self,widget,currentPage):
if currentPage == '' or str(notebook.get_current_page()) != currentPage:
self.get_window().set_cursor(hand_cursor)
def cursorHandOff(self,widget):
self.get_window().set_cursor()
def get_packages():
global listbox, listbox_aur, packs, items_pacman_info, items_aur_info, pacman_array, aur_array, pkgbuild_array, aur_array_info
listbox = Gtk.ListBox()
listbox.set_selection_mode(2)
listbox_aur = Gtk.ListBox()
listbox_aur.set_selection_mode(2)
pacman_array = []
aur_array = []
try:
socket.create_connection(("
www.google.com", 80))
if apply_button.get_sensitive() != True: apply_button.set_sensitive(True)
packs = os.popen('checkupdates').read()
packs = packs.split("\n")
ii = 0
items_pacman_info = []
for i in packs[:-1]:
pacman_array.append(i.split(' ', 1)[0])
items_pacman = Gtk.MenuItem()
items_pacman.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
items_pacman.connect('enter-notify-event', cursorHandOn, '')
items_pacman.connect('leave-notify-event', cursorHandOff)
items_pacman.set_label(i.split(' ', 1)[0])
items_pacman_info.append([s for s in packs if i.split(' ', 1)[0] in s][0]+'\n'+os.popen('pacman -Si %s'% i.split(' ', 1)[0]).read())
items_pacman.set_tooltip_text([s for s in packs if i.split(' ', 1)[0] in s][0]+'\n'+os.popen('pacman -Si %s'% i.split(' ', 1)[0]).read().rstrip())
listbox.insert(items_pacman, ii)
if switch3.get_active(): items_pacman.set_has_tooltip(True)
else: items_pacman.set_has_tooltip(False)
ii += 1
frame1.set_label('PACMAN ({})'.format(ii))
listbox.connect('row-selected', pacman_show)
##################################
## get installable aur packages ##
##################################
ii = 0
pkgbuild_array = []
aur_array_info = []
items_aur_info = []
aur = os.popen('pacman -Qqm').read()
for i in range (0,(aur.count('\n'))):
with urllib.request.urlopen("
https://aur.archlinux.org/rpc.php?v=5&type=info&arg=%s"% aur.split('\n', -1)
) as url:
data = json.loads(url.read().decode())
if data['resultcount'] != 0:
version_old = os.popen('pacman -Qi %s | grep \"Versione\" | awk \'{print$3}\''% aur.split('\n', -1)).read()
if version_old.rstrip() != data['results'][0]['Version']:
version_new = data['results'][0]['Version']
filename = Path('/home/'+user+'/.cache/AUR/'+aur.split('\n', -1)+'/'+aur.split('\n', -1)+'.tar.gz')
if filename.exists():
hash_old = hashlib.md5(open(filename,'rb').read()).hexdigest()
else: hash_old = ''
hash_new = os.popen('curl -s https://aur.archlinux.org/cgit/aur.git/snapshot/\"%s.tar.gz\" | md5sum | awk \'{print$1}\''% aur.split('\n', -1)).read()
if hash_old != hash_new.rstrip() or hash_old == '':
aur_array.append(aur.split('\n', -1))
aur_array_info.append(aur.split('\n', -1))
items_aur = Gtk.MenuItem()
items_aur.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
items_aur.connect('enter-notify-event', cursorHandOn, '')
items_aur.connect('leave-notify-event', cursorHandOff)
items_aur.set_label(aur.split('\n', -1))
items_aur_info.append(os.popen('pacman -Qi %s'% aur.split('\n', -1)).read())
items_aur.set_tooltip_text(os.popen('pacman -Qi %s'% aur.split('\n', -1)).read().rstrip())
listbox_aur.insert(items_aur, ii)
url = "https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=%s"% aur.split('\n', -1)
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, "lxml")
for script in soup(["script", "style"]):
script.extract()
text = soup.get_text()
lines = (line.strip() for line in text.splitlines())
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
text_pkgbuild = '\n'.join(chunk for chunk in chunks if chunk)
pkgbuild_array.append('# Maintainer:'+text_pkgbuild.split("# Maintainer:",1)[1])
if switch3.get_active(): items_aur.set_has_tooltip(True)
else: items_aur.set_has_tooltip(False)
ii += 1
frame2.set_label('AUR ({})'.format(ii))
listbox_aur.connect('row-selected', aur_show)
listbox_aur.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
listbox_aur.connect("motion-notify-event", on_pointer_motion)
if not self.page2.get_sensitive():
self.page2.set_sensitive(True)
image_options.set_tooltip_text("options")
internet = 1
except OSError:
internet = 0
items_pacman = Gtk.MenuItem()
items_pacman.set_label('no internet connection!')
listbox.insert(items_pacman, 0)
if apply_button.get_sensitive() == True: apply_button.set_sensitive(False)
frame1.set_label('PACMAN')
frame2.set_label('AUR')
frame3.set_label('')
items_aur = Gtk.MenuItem()
items_aur.set_label('no internet connection!')
listbox_aur.insert(items_aur, 0)
listbox.unselect_all()
listbox_aur.unselect_all()
if self.page2.get_sensitive():
self.page2.set_sensitive(False)
image_options.set_tooltip_text("options disabled: no internet")
if (len(pacman_array) == 0 and len(aur_array) == 0 and switch1.get_active() == False and switch2.get_active() == False) or internet == 0:
if apply_button.get_sensitive() == True: apply_button.set_sensitive(False)
GLib.idle_add(show_listboxes)
def refresh_function(_):
self.set_sensitive(False)
if self.swin.get_child(): self.swin.remove(self.swin.get_child())
if self.swin1.get_child(): self.swin1.remove(self.swin1.get_child())
if self.swin2.get_child(): self.swin2.remove(self.swin2.get_child())
frame1.set_label('PACMAN')
frame2.set_label('AUR')
frame3.set_label('')
thread = threading.Thread(target=get_packages)
thread.daemon = True
thread.start()
def pacman_show(self, widget):
if listbox.get_selected_row():
row = listbox.get_selected_row()
menuitem_label = row.get_child().get_label()
if row.get_opacity() == 1:
row.set_opacity(0.5)
pacman_array.remove(menuitem_label)
else:
row.set_opacity(1)
pacman_array.append(menuitem_label)
listbox.unselect_row(row)
if len(pacman_array) == 0 and len(aur_array) == 0 and switch1.get_active() == False and switch2.get_active() == False:
if apply_button.get_sensitive() == True: apply_button.set_sensitive(False)
return False
def aur_show(self, widget):
if listbox_aur.get_selected_row():
row = listbox_aur.get_selected_row()
auritem_label = row.get_child().get_label()
if row.get_opacity() == 1:
row.set_opacity(0.5)
aur_array.remove(auritem_label)
else:
row.set_opacity(1)
aur_array.append(auritem_label)
listbox_aur.unselect_row(row)
if len(pacman_array) == 0 and len(aur_array) == 0 and switch1.get_active() == False and switch2.get_active() == False:
if apply_button.get_sensitive() == True: apply_button.set_sensitive(False)
return False
def show_pkgbuild():
if self.swin2.get_child(): self.swin2.remove(self.swin2.get_child())
self.swin2.add(pkgbuild_label)
pkgbuild_label.show()
return False
def on_pointer_motion(self, widget):
global pkgbuild_label
if switch4.get_active() and aur_array:
row_y = listbox_aur.get_pointer()
pkgbuild_label = Gtk.Label()
index = aur_array_info.index(listbox_aur.get_row_at_y(row_y[1]).get_child().get_label())
pkgbuild_label.set_text(pkgbuild_array[index])
GLib.idle_add(show_pkgbuild)
def refresh_button_clicked():
GLib.source_remove(refresh_button_clicked_id)
refresh_button.clicked()
notebook = Gtk.Notebook()
self.add(notebook)
##################
# upgrading page #
##################
self.page1 = Gtk.VBox(homogeneous=False, spacing=10)
self.hbox1 = Gtk.HBox(homogeneous=True, spacing=10)
self.vbox_packages = Gtk.VBox(homogeneous=True, spacing=10)
self.page1.set_border_width(10)
frame1 = Gtk.Frame()
label_widget_pacman = Gtk.Label()
label_widget_pacman.set_markup('<b>PACMAN</b>')
frame1.set_label_widget(label_widget_pacman)
frame2 = Gtk.Frame()
label_widget_aur = Gtk.Label()
label_widget_aur.set_markup('<b>AUR</b>')
frame2.set_label_widget(label_widget_aur)
frame3 = Gtk.Frame()
frame3.set_label('')
apply_button = Gtk.Button()
apply_button.set_label('Apply')
apply_button.connect("clicked", apply_function, '')
apply_button.connect('enter-notify-event', cursorHandOn, '')
apply_button.connect('leave-notify-event', cursorHandOff)
apply_button.set_name('apply')
refresh_button = Gtk.Button()
refresh_button.set_label('Refresh')
refresh_button.connect("clicked", refresh_function)
refresh_button.connect('enter-notify-event', cursorHandOn, '')
refresh_button.connect('leave-notify-event', cursorHandOff)
refresh_button.set_name('refresh')
self.swin = Gtk.ScrolledWindow()
frame1.add(self.swin)
self.swin1 = Gtk.ScrolledWindow()
frame2.add(self.swin1)
self.swin2 = Gtk.ScrolledWindow()
frame3.add(self.swin2)
self.vbox_packages.pack_start(frame1, True, True, 0)
self.vbox_packages.pack_start(frame2, True, True, 0)
self.hbox1.pack_start(self.vbox_packages, True, True, 10)
self.hbox1.pack_start(frame3, True, True, 10)
self.page1.add(self.hbox1)
hbox5 = Gtk.HBox(homogeneous=False, spacing=10)
hbox5.pack_end(apply_button, False, False, 10)
hbox5.pack_end(refresh_button, False, False, 0)
hbox5.pack_start(self.spinner, True, True, 0)
self.page1.pack_end(hbox5, False, False, 0)
image_upgrading = Gtk.Image()
image_upgrading.set_from_icon_name("system-software-install", Gtk.IconSize.DND)
image_upgrading.set_tooltip_text("update")
image_upgrading.show()
eventBox1 = Gtk.EventBox()
eventBox1.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
eventBox1.connect('enter-notify-event', cursorHandOn, '0')
eventBox1.connect('leave-notify-event', cursorHandOff)
eventBox1.add(image_upgrading)
eventBox1.show()
notebook.append_page(self.page1, eventBox1)
################
# options page #
################
self.page2 = Gtk.VBox()
self.page2.set_border_width(10)
image_options = Gtk.Image()
image_options.set_from_icon_name("preferences-desktop", Gtk.IconSize.DND)
image_options.set_tooltip_text("options")
image_options.show()
eventBox2 = Gtk.EventBox()
eventBox2.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
eventBox2.connect('enter-notify-event', cursorHandOn, '1')
eventBox2.connect('leave-notify-event', cursorHandOff)
eventBox2.add(image_options)
eventBox2.show()
notebook.append_page(self.page2, eventBox2)
frame5 = Gtk.Frame()
frame5.set_label('OPTIONS')
vbox_options = Gtk.VBox(homogeneous=False,spacing=0)
hbox_cache = Gtk.HBox()
cache = Gtk.Label()
cache.set_markup("<b>Clear Cache</b>")
switch1 = Gtk.Switch()
switch1.connect("notify::active", on_switch_activated)
switch1.connect('enter-notify-event', cursorHandOn, '')
switch1.connect('leave-notify-event', cursorHandOff)
switch1.set_active(False)
vbox_options.pack_start(Gtk.Separator().new(0),False,False,10)
numbers = Gtk.Label()
numbers.set_markup("")
combobox = Gtk.ComboBoxText()
combobox.insert(0, "0", "0")
combobox.insert(1, "1", "1")
combobox.insert(2, "2", "2")
combobox.insert(3, "3", "3")
combobox.insert(4, "4", "4")
combobox.insert(5, "5", "5")
combobox.set_active(3)
combobox.set_sensitive(False)
combobox.connect('enter-notify-event', cursorHandOn, '')
combobox.connect('leave-notify-event', cursorHandOff)
hbox_cache.pack_start(cache, False, False, 10)
hbox_cache.pack_start(switch1, True, False, 10)
hbox_cache.pack_end(combobox, False, False, 10)
hbox_cache.pack_end(numbers, False, False, 10)
vbox_options.pack_start(hbox_cache, False, False, 10)
vbox_options.pack_start(Gtk.Separator().new(0),False,False,10)
hbox_orphans = Gtk.HBox(homogeneous=False, spacing=35)
orphans = Gtk.Label()
orphans.set_markup("<b>Remove Orphans</b>")
orphans.set_justify(Gtk.Justification.LEFT)
hbox_orphans.pack_start(orphans, False, False, 10)
switch2 = Gtk.Switch()
switch2.connect("notify::active", on_switch_activated)
switch2.connect('enter-notify-event', cursorHandOn, '')
switch2.connect('leave-notify-event', cursorHandOff)
switch2.set_active(False)
hbox_orphans.pack_end(switch2, False, False, 10)
vbox_options.pack_start(hbox_orphans, False, False, 10)
vbox_options.pack_start(Gtk.Separator().new(0),False,False,10)
hbox_tooltip = Gtk.HBox(homogeneous=False, spacing=35)
tooltip = Gtk.Label()
tooltip.set_markup("<b>Tooltip as Package Info</b>")
tooltip.set_justify(Gtk.Justification.LEFT)
hbox_tooltip.pack_start(tooltip, False, False, 10)
switch3 = Gtk.Switch()
switch3.connect("notify::active", tooltip_info)
switch3.connect('enter-notify-event', cursorHandOn, '')
switch3.connect('leave-notify-event', cursorHandOff)
switch3.set_active(False)
hbox_tooltip.pack_end(switch3, False, False, 10)
vbox_options.pack_start(hbox_tooltip, False, False, 10)
vbox_options.pack_start(Gtk.Separator().new(0),False,False,10)
hbox_pkgbuild = Gtk.HBox(homogeneous=False, spacing=35)
pkgbuild = Gtk.Label()
pkgbuild.set_markup("<b>Show new PKGBUILD</b>")
pkgbuild.set_justify(Gtk.Justification.LEFT)
hbox_pkgbuild.pack_start(pkgbuild, False, False, 10)
switch4 = Gtk.Switch()
switch4.connect("notify::active", pkgbuild_info)
switch4.connect('enter-notify-event', cursorHandOn, '')
switch4.connect('leave-notify-event', cursorHandOff)
switch4.set_active(False)
hbox_pkgbuild.pack_end(switch4, False, False, 10)
vbox_options.pack_start(hbox_pkgbuild, False, False, 10)
vbox_options.pack_start(Gtk.Separator().new(0),False,False,10)
hbox_manager = Gtk.HBox(homogeneous=False, spacing=35)
manager_install = Gtk.Button()
manager_install.set_name('install')
manager_install.set_label("INSTALL package")
manager_install.connect('clicked', apply_function, 'install')
manager_install.connect('enter-notify-event', cursorHandOn, '')
manager_install.connect('leave-notify-event', cursorHandOff)
hbox_manager.pack_start(manager_install, True, True, 10)
manager_remove = Gtk.Button()
manager_remove.set_name('remove')
manager_remove.set_label("REMOVE package")
manager_remove.connect('clicked', apply_function, 'remove')
manager_remove.connect('enter-notify-event', cursorHandOn, '')
manager_remove.connect('leave-notify-event', cursorHandOff)
hbox_manager.pack_start(manager_remove, True, True, 10)
vbox_options.pack_start(hbox_manager, True, True, 25)
frame5.add(vbox_options)
self.page2.pack_start(frame5, True, True, 0)
hbox_buttons = Gtk.HBox(homogeneous=False, spacing=0)
self.page2.pack_end(hbox_buttons, False, False, 15)
#############
# info page #
#############
self.page3 = Gtk.Box()
self.page3.set_border_width(10)
info = Gtk.Label()
info.set_markup('\n<b><big>UPDATING_ARCH_MANAGER</big></b>\n<i>version 1.0-2019</i>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <a href=\"http://www.gnu.org/licenses/\" title=\"open in browser: <i>http://www.gnu.org/licenses/</i>\"><i>this link</i></a>.\n')
info.set_justify(Gtk.Justification.CENTER)
self.page3.add(info)
image_info = Gtk.Image()
image_info.set_from_icon_name("help-about", Gtk.IconSize.DND)
image_info.set_tooltip_text("info")
image_info.show()
eventBox3 = Gtk.EventBox()
eventBox3.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
eventBox3.connect('enter-notify-event', cursorHandOn, '2')
eventBox3.connect('leave-notify-event', cursorHandOff)
eventBox3.add(image_info)
eventBox3.show()
notebook.append_page(self.page3, eventBox3)
################
# END OF PAGES #
################
def on_change_status_notebook(self, widget):
if self.get_sensitive(): self.spinner.stop()
else: self.spinner.start()
def popoverShow():
popover = Gtk.Popover().new(info_warning)
popover.set_property('width-request', 200)
popover.add(labelInfo)
popover.set_position(Gtk.PositionType.BOTTOM)
popover.set_modal(False)
popover.show_all()
popover.popup()
def mouseEnterInfo(self, event):
self.get_window().set_cursor(hand_cursor)
global popover
if not popover:
popover = Gtk.Popover().new(info_warning)
popover.set_property('width-request', 200)
popover.add(labelInfo)
popover.set_position(Gtk.PositionType.BOTTOM)
popover.set_modal(False)
popover.show_all()
popover.popup()
else:
if popover.get_visible() == False:
popover = Gtk.Popover().new(info_warning)
popover.set_property('width-request', 200)
popover.add(labelInfo)
popover.set_position(Gtk.PositionType.BOTTOM)
popover.set_modal(False)
popover.show_all()
popover.popup()
def popoverFadingOut():
popover.set_opacity(popover.get_opacity() - 0.01)
if popover.get_opacity() == 0:
popover.destroy()
return False
else:
return True
def mouseLeaveInfo(self, event):
self.get_window().set_cursor()
GLib.timeout_add(5, popoverFadingOut)
global popover
popover = None
labelInfo = Gtk.Label()
labelInfo.set_markup("\n<b><big><span color='red'>»:: Information Dialog ::«</span></big></b>\n\n<span color='white'><i>Updated AUR package is stored in:\n<b>/home/$USER/.cache/AUR/$package</b>\n with only saved archive <b>.tar.gz</b> and <b>.pkg.tar.xz</b> files,\n\nwhile the pkg cache is stored in:\n<b>/home/$USER/.cache/AUR/$package/PKG</b>.</i></span>\n")
labelInfo.set_justify(Gtk.Justification.CENTER)
window_close.connect('button-press-event', exit_function)
window_close.connect('enter-notify-event', cursorHandOn, '')
window_close.connect('leave-notify-event', cursorHandOff)
info_warning.connect('enter-notify-event', mouseEnterInfo)
info_warning.connect('leave-notify-event', mouseLeaveInfo)
self.set_sensitive(False)
notebook.connect_after("switch-page", on_changed_page)
self.connect("state-changed", on_change_status_notebook)
refresh_button_clicked_id = GLib.idle_add(refresh_button_clicked)
##############
# end of gui #
##############
css = b"""
@keyframes fading-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes shadow-pulse {
0% { box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.2); }
100% { box-shadow: 0 0 0 25px rgba(0, 0, 0, 0); }
}
#window-self {
animation: fading-in 1s 1;
}
#install, #remove {
font-weight: bold;
}
#previous:hover, #close:hover, #apply:hover, #refresh:hover, #install:hover, #remove:hover {
animation: shadow-pulse 1s 1;
border-radius: 30px;
opacity: 0.8;
}
#refresh:active, #apply:active, #exit:active, #install:active, #remove:active {
background-image: none;
background-color: lightgray;
opacity: 0.4;
}
tooltip {
border-radius: 5px;
}
#exit {
background-image: none;
background-color: transparent;
border-radius: 50%;
padding: 0px 0px;
border: none;
color: black;
opacity: 0.3;
}
#exit:hover {
background-image: none;
background-color: transparent;
color: red;
border: none;
animation: shadow-pulse 0.5s 1;
opacity: 1;
}
#info {
background-image: none;
background-color: transparent;
border-radius: 50%;
padding: 0px 0px;
border: none;
color: black;
opacity: 0.3;
}
#info:hover {
background-image: none;
background-color: transparent;
border: none;
opacity: 1;
}
@keyframes popover-fading {
0% { background-color: rgba(0,0,0,0); }
100% { background-color: rgba(0,0,0,0.7); }
}
popover {
padding: 10px;
background-image: none;
background-color: rgba(0,0,0,0.7);
border-radius: 10px;
animation: popover-fading 1s 1;
}
"""
style_provider = Gtk.CssProvider()
style_provider.load_from_data(css)
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()