Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I would like to make a button to sit up next to my sound/wireless/etc indicators which, when toggled, will change color and write the system time with the word "begin" to a file, then, when toggled again, return to its original color and record the system time with the word "end." Ideally, the button would maintain it's toggled/untoggled state even if the system restarts.

I can't imagine this would be a difficult program to make at all, but I am a bit new to Ubuntu and I'm not sure how to make a program work as an indicator, or how to make something maintain its state on system restart.

share|improve this question
    
See here and here (specially the Python version). –  edwin Jun 23 '13 at 23:59
add comment

2 Answers

up vote 2 down vote accepted

I got interested so here is my Python code:

#!/usr/bin/python

from time import time, ctime
from gi.repository import Gtk
from gi.repository import AppIndicator3 as Indicator


MY_FILENAME = '/home/your-username/myfile.log'
MY_INDICATOR_ID = 'my-indicator-example'
STOP_ICON_NAME = 'indicator-messages'
START_ICON_NAME = 'indicator-messages-new'

class MyIndicator(object):

    def __init__(self, filename):
        self.indicator = Indicator.Indicator.new(
                                MY_INDICATOR_ID,
                                STOP_ICON_NAME,
                                Indicator.IndicatorCategory.APPLICATION_STATUS)

        self.indicator.set_status(Indicator.IndicatorStatus.ACTIVE)
        self.indicator.set_attention_icon(START_ICON_NAME)

        self.has_started = False

        self.menu = Gtk.Menu()

        start_item = Gtk.MenuItem('Start')
        start_item.connect('activate', self.start_activated, filename)
        self.menu.append(start_item)
        start_item.show()

        stop_item = Gtk.MenuItem('Stop')
        stop_item.connect('activate', self.stop_activated, filename)
        self.menu.append(stop_item)
        stop_item.show()

        self.indicator.set_menu(self.menu)

    def main(self):
        Gtk.main()

    def start_activated (self, menu_item, filename):
        if not self.has_started:
            myfile = open(filename, 'a')
            myfile.write('Start  <%s>\n' % ctime(time()))
            self.indicator.set_status(Indicator.IndicatorStatus.ATTENTION)
            self.has_started = True

    def stop_activated (self, menu_item, filename):
        if self.has_started:
            myfile = open(filename, 'a')
            myfile.write('End    <%s>\n' % ctime(time()))
            self.indicator.set_status(Indicator.IndicatorStatus.ACTIVE)
            self.has_started = False


if __name__ == '__main__':
    indicator = MyIndicator(MY_FILENAME)
    indicator.main()

I used the info given by gpaste-indicator and the Ubuntu Wiki. I'm not sure about the "keeping the state between restarts" feature, the simplest would be to read the last line of myfile.log and setting self.has_started accordingly. Good luck.

share|improve this answer
    
Thanks so much. This code has been very instructive to me. –  Alexander Nikolas Gruber Jun 25 '13 at 21:06
    
I was able to massage your code to do everything I wanted. I'll post the full app as a separate answer. Thanks again! –  Alexander Nikolas Gruber Jul 13 '13 at 23:40
add comment

I was able to modify and improve the code from edwin's very helpful answer so that the app does keep state between restarts! I'm using it all the time now.

For anyone else who wants to use it, here it is (also available on pastebin):

#!/usr/bin/python

from time import time, ctime
from gi.repository import Gtk
from gi.repository import AppIndicator3 as Indicator
from datetime import datetime, date


MY_FILENAME = '/home/anotherghost/workhours.log'
MY_INDICATOR_ID = 'work-hours-indicator'
STOP_ICON_NAME = 'indicator-messages'
START_ICON_NAME = 'indicator-messages-new'
FMT = "%a %b %d %H:%M:%S %Y"

class MyIndicator(object):

    def __init__(self, filename):
        self.indicator = Indicator.Indicator.new(
                                MY_INDICATOR_ID,
                                STOP_ICON_NAME,
                                Indicator.IndicatorCategory.APPLICATION_STATUS)

        self.menu = Gtk.Menu()

        start_item = Gtk.MenuItem('Start')
        start_item.connect('activate', self.start_activated, filename)
        self.menu.append(start_item)
        start_item.show()

        stop_item = Gtk.MenuItem('Stop')
        stop_item.connect('activate', self.stop_activated, filename)
        self.menu.append(stop_item)
        stop_item.show()

        showall_item = Gtk.MenuItem('Show all')
        showall_item.connect('activate', self.showall, filename)
        self.menu.append(showall_item)
        showall_item.show()

        self.indicator.set_menu(self.menu)
        self.indicator.set_attention_icon(START_ICON_NAME)

        with open(MY_FILENAME,'r') as fn:
            try:
                fn.seek(-70, 2)
            except (IndexError, IOError):
                fn.seek(max(-len(fn.read().decode()),-69),2)
            self.last = fn.readlines()[-1].decode()
            if len(self.last) > 1 and len(self.last) < 30:
                self.last = self.last.split(" ")
                self.last[-1] = self.last[-1][:4]
                self.last = " ".join(self.last)
                self.start_time = datetime.strptime(self.last, FMT)
                self.indicator.set_status(Indicator.IndicatorStatus.ATTENTION)
                self.has_started = True
                self.end_time = datetime.now()
            else:
                self.indicator.set_status(Indicator.IndicatorStatus.ACTIVE)
                self.has_started = False
                self.start_time = datetime.now()
                self.end_time = datetime.now()


    def main(self):
        Gtk.main()

    def start_activated (self, menu_item, filename):
        if not self.has_started:
            myfile = open(filename, 'a')
            self.start_time = datetime.now()
            myfile.write('%s' % self.start_time.strftime(FMT))
            self.indicator.set_status(Indicator.IndicatorStatus.ATTENTION)
            self.has_started = True
            myfile.close()

    def stop_activated (self, menu_item, filename):
        if self.has_started:
            myfile = open(filename, 'r+')
            myfile.seek(-1, 2)
            if myfile.read(1) == '\n':
                myfile.seek(-1, 2)
            self.end_time = datetime.now()
            self.elapsed_time = self.end_time - self.start_time
            myfile.write('\t%s\t' % self.end_time.strftime(FMT))
            myfile.write('%s\n' % round(float(self.elapsed_time.seconds)/3600,3) )
            self.indicator.set_status(Indicator.IndicatorStatus.ACTIVE)
            self.has_started = False
            myfile.close()

    def showall (self, menu_item, filename):
        myfile = open('op.log', 'a')
        myfile.write('has_started: %s\n' % self.has_started)
        myfile.write('start_time: %s\n' % self.start_time.strftime(FMT))
        myfile.write('end_time: %s\n' % self.end_time.strftime(FMT))


if __name__ == '__main__':
    indicator = MyIndicator(MY_FILENAME)
    indicator.main()
share|improve this answer
    
+1 Good job! –  edwin Jul 13 '13 at 23:44
1  
But you should edit the code you've paste, try not using tab characters for the indentation instead use four spaces (you can configure that in GEdit). –  edwin Jul 13 '13 at 23:54
    
@edwin Got it, done. –  Alexander Nikolas Gruber Jul 14 '13 at 6:28
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.