You are not logged in.

#1 2014-10-03 09:17:28

Nektarios
Member
Registered: 2013-02-19
Posts: 90

a KISS systray pacman/aur updates checker for KDE

I have created a simple python-QT script that places an icon in the system tray and informs you when updates for both pacman and AUR are available. Also I created a bash script that does the real package updates checking. The python script depends on python 3, kde which must be installed and PyQt4 perl module. The bash scripts depends on cower.

I could have built the whole functionality in only the python script, but I thought that the best way was to separate the checking and the notification parts to keep it simple and flexible.

I thought that I should share them as they are very convenient for me and they work well for a long time now.

They feature:

- automatically checking for updates both for arch official repos and AUR
- notifies the user by changing the icon accordingly if there are updates available
- by clicking on the icon you get a balloon with a list of the availabe (and ignored) updates for packages
- automatically refreshes after every pacman upgrade/installation/removal of packages
- ability to ignore some updates for packages that you don't wish to upgrade and not get notified for them (but they still get printed as ignored on the list in the icon's balloon)
- no root permission needed
- it only CHECKS and does absolutely nothing else. It does not change your system, your packages or your pacman database.

Here's a quick summary of how they work:

The bash script calls checkupdates and cower -u to produce a list of available updates both for arch official repos and AUR and it stores this list in two temporary files. The python script simply checks those two temporary files each second and gets the package names and updates count, which in turn notifies the user for them. It also checks each second /var/log/pacman for modification (for a way to know when there's been a change in the installed packages) and if it is, then it calls the bash script to update the temporary files.

Instructions:

1. place the python script somewhere in your system and add it to the KDE Autostart.
2. place the bash script also anywhere and add it to a cron job that runs hourly (or whatever other interval you wish)
3. change the paths in the python script accordingly to reflect correctly the paths of the various files your system
4. optional: create a file for the ignored packages, where you can list each package name in a new line for those packages that you wish to be ignored. Also don't forget to update the python script with the correct path for this particular file.

And that's it. From now on you get a nice icon in your systray that is green when you system is "up to date" and yellow with exclamation mark when updates are available. I hope you like it.

Tell me if they work for you, or you have issues so I can fix them.

Also if you want something to be added or have some good idea or maybe you would want them to work for other DEs, I am open to ideas and suggestions for expanding them and making them better. But remember I am keen on the KISS idea and I will keep them as simple as possible.

check-system-updates.py

#! /usr/bin/env python
from PyQt4 import QtGui, QtCore
import os
import re
import os.path, time

class RightClickMenu(QtGui.QMenu):
    def __init__(self, parent=None):
        QtGui.QMenu.__init__(self, "Edit", parent)

        exit = QtGui.QAction(QtGui.QIcon('icons/exit.png'), 'Exit', self)
        exit.setShortcut('Ctrl+Q')
        exit.setStatusTip('Exit application')
        
        exit.triggered.connect(QtGui.qApp.quit)
        self.addAction(exit)
        
    
class LeftClickMenu(QtGui.QMenu):
    def __init__(self, parent=None):
        QtGui.QMenu.__init__(self, "File", parent)

class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, parent)
        
        # file paths:
        
        self.synchronizeScriptPath = '~/Scripts/synchronize-and-count-system-updates.sh';
        self.ignoreFilenameAndPath = '~/.config/system-check-updates-ignore.txt';
        self.pacmanlogFilenameAndPath = '/var/log/pacman.log';
        self.updateCountPath = '/tmp/updateCount';
        self.updateListPath = '/tmp/updateList';
        
        self.iconOK = QtGui.QIcon("/usr/share/icons/oxygen/22x22/status/security-high.png")
        self.iconProblem = QtGui.QIcon("/usr/share/icons/oxygen/22x22/status/security-medium.png")
        
        self.status = 1
        self.updateCount = 0;
        self.updateList = [];
        self.updateIgnoredCount = 0;
        self.updateIgnoredList = [];
        self.pacmanlogLastModificationTime = 0;
        
        
        self.setIcon(self.iconProblem);
        self.right_menu = RightClickMenu()
        self.setContextMenu(self.right_menu)
        self.activated.connect(self.click_trap)

    def click_trap(self, value):
        if value == self.Trigger: #left click!
            if self.updateIgnoredCount > 0:
                ignoredMessage = "\n\nIgnored " + str(self.updateIgnoredCount) + " updates:\n\n" + '\n'.join(self.updateIgnoredList) + '\n\n' + 'Using ignore file: ' + self.ignoreFilenameAndPath
            else:
                ignoredMessage = ""
            
            if self.status == 1:
                self.showMessage("There are " + str(self.updateCount) + " new updates", '\n'.join(self.updateList) + ignoredMessage, QtGui.QSystemTrayIcon.Information, 4000);
            else:
                self.showMessage("System Updates Status", "System up to date" + ignoredMessage, QtGui.QSystemTrayIcon.Warning, 5000);
        
    def show(self):
        QtGui.QSystemTrayIcon.show(self)
    
    def checkSystemUpdates(self):
        # check if pacman.log has been updated
        newPacmanlogModificationTime = os.path.getmtime(self.pacmanlogFilenameAndPath);
        if newPacmanlogModificationTime > self.pacmanlogLastModificationTime:
            #print("pacman.log modified")
            f = os.popen(self.synchronizeScriptPath)
            commandSynchronizeAndCountSystemUpdates = f.read()
            #print("executing check updates script")
            self.pacmanlogLastModificationTime = newPacmanlogModificationTime;
            #print("check updates finished")
        #print("last modified: %s", time.ctime(os.path.getmtime(self.pacmanlogFilenameAndPath)))
        #print("last modified: %d", os.path.getmtime(self.pacmanlogFilenameAndPath))
        #print("created: %s", time.ctime(os.path.getctime(self.pacmanlogFilenameAndPath)))
		
        f = os.popen('cat ' + self.ignoreFilenameAndPath)
        commandCatIgnoreFileOutput = f.read()
        
        f = os.popen('cat ' + self.updateCountPath)
        commandOutput = f.read()
        
        f = os.popen('cat ' + self.updateListPath)
        command2Output = f.read()
        
        self.updateCount = 0
        self.updateList = []
        self.updateIgnoredCount = 0;
        self.updateIgnoredList = [];
        
        for line in command2Output.split('\n'):
           if line:
               fileIgnored = False
               for ignoreLine in commandCatIgnoreFileOutput.split('\n'):
                   if ignoreLine:
                       if ignoreLine in line:
                           fileIgnored = True
                           
               if fileIgnored != True:
                   self.updateCount += 1
                   self.updateList.append(line)
               else:
                   self.updateIgnoredCount += 1;
                   self.updateIgnoredList.append(line);
                   #print("ignored: " + line)
               #print(str(i) + " " + line)
               
        #print("command output: " + commandOutput)
        #print("command 2 output: " + command2Output)
        #self.updateCount = int(commandOutput)
        #print(self.updateCount)
        
        if self.updateCount > 0:
            #print("found updates, self.updateCount = " + str(self.updateCount) + ", self.status = " + str(self.status));
            if self.status == 0:
                #print("status is 0, changing it to 1, self.status = " + str(self.status));
                self.status = 1;
                self.setIcon(self.iconProblem)
                #print("setting icon problem, self.updateCount = " + str(self.updateCount));
            
        else:
            #print("no updates, self.updateCount = " + str(self.updateCount) + ", self.status = " + str(self.status));
            if self.status == 1:
                #print("status is 1, changing it to 0, self.status = " + str(self.status));
                self.status = 0
                self.setIcon(self.iconOK)
                #print("setting icon OK, self.updateCount = " + str(self.updateCount));
    
def main():
    
    import sys
    import signal
    
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    app = QtGui.QApplication(sys.argv)
    
    tray = SystemTrayIcon()
    
    # creat timer to call main checking function
    timer = QtCore.QTimer()
    timer.timeout.connect(tray.checkSystemUpdates);
    timer.start(1000);
        
    tray.show()
    
    sys.exit(app.exec_())

if __name__ == "__main__":
	main()

synchronize-and-count-system-updates.sh

#!/bin/bash
 
pacmanUpdates=$(/usr/bin/checkupdates)

if [ -n "$pacmanUpdates" ]; then
	pacmanUpdatesCount=$(echo "$pacmanUpdates" | wc -l)
else
	pacmanUpdatesCount=0	
fi
aurUpdates=$(/usr/bin/cower -u)

if [ -n "$aurUpdates" ]; then
	aurUpdatesCount=$(echo "$aurUpdates" | wc -l)
else
	aurUpdatesCount=0
fi
updateCount=$(($pacmanUpdatesCount + $aurUpdatesCount))

> /tmp/updateList
if [ -n "$pacmanUpdates" ]; then
	echo "$pacmanUpdates" >> /tmp/updateList
fi

if [ -n "$aurUpdates" ]; then
	echo "$aurUpdates" >> /tmp/updateList
fi
echo "$updateCount" > /tmp/updateCount

Last edited by Nektarios (2014-10-06 19:05:39)

Offline

#2 2014-10-03 10:19:31

Spyhawk
Member
Registered: 2006-07-07
Posts: 485

Re: a KISS systray pacman/aur updates checker for KDE

Hem, since KDE 5 is on the way... any plan to port this to Qt5/PyQt5?

Offline

#3 2014-10-03 11:52:30

Nektarios
Member
Registered: 2013-02-19
Posts: 90

Re: a KISS systray pacman/aur updates checker for KDE

Well I see no reason why it will not work with pyqt5 or kde 5. Just try it. Otherwise I will update it when I myself will get on KDE 5 and that will be when arch will officially move on.

Offline

#4 2014-10-03 14:46:43

Spyhawk
Member
Registered: 2006-07-07
Posts: 485

Re: a KISS systray pacman/aur updates checker for KDE

Yes, sorry for my dumb question. I guess I actually wanted to ask if you planned to maintain an official Qt5 version. Also, might be useful to add your script in the AUR and to reference it in the wiki.

Offline

Board footer

Powered by FluxBB