summaryrefslogtreecommitdiffstats
path: root/BitTorrent/StatusLight.py
blob: 11cbf14180a74166ea6d3eef3e743abb134ea847 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from BitTorrent.platform import bttime

class StatusLight(object):

    initial_state = 'stopped'

    states = {
        # state     : (stock icon name, tool tip),
        'stopped'   : ('bt-status-stopped',
                       _("Paused")),
        'empty'     : ('bt-status-stopped',
                       _("No torrents")),
        'starting'  : ('bt-status-starting',
                       _("Starting download")),
        'pre-natted': ('bt-status-pre-natted',
                       _("Starting download")),
        'running'   : ('bt-status-running',
                       _("Running normally")),
        'natted'    : ('bt-status-natted',
                       _("Downloads may be slow:\nProbably firewalled/NATted")),
        'broken'    : ('bt-status-broken',
                       _("Check network connection")),
        }

    messages = {
        # message           : default new state,
        'stop'              : 'stopped'   ,
        'empty'             : 'empty'     ,
        'start'             : 'starting'  ,
        'seen_peers'        : 'pre-natted',
        'seen_remote_peers' : 'running'   ,
        'broken'            : 'broken'    ,
        }
    
    transitions = {
        # state      : { message            : custom new state, },
        'pre-natted' : { 'start'            : 'pre-natted',
                         'seen_peers'       : 'pre-natted',},
        'running'    : { 'start'            : 'running'   ,
                         'seen_peers'       : 'running'   ,},
        'natted'     : { 'start'            : 'natted'    ,
                         'seen_peers'       : 'natted'    ,},
        'broken'     : { 'start'            : 'broken'    ,},
        #TODO: add broken transitions
        }

    time_to_nat = 60 * 5 # 5 minutes

    def __init__(self):
        self.mystate = self.initial_state
        self.start_time = None

    def send_message(self, message):
        if message not in self.messages.keys():
            #print 'bad message', message
            return
        new_state = self.messages[message]
        if self.transitions.has_key(self.mystate):
            if self.transitions[self.mystate].has_key(message):
                new_state = self.transitions[self.mystate][message]

        # special pre-natted timeout logic
        if new_state == 'pre-natted':
            if (self.mystate == 'pre-natted' and
                bttime() - self.start_time > self.time_to_nat):
                # go to natted state after a while
                new_state = 'natted'
            elif self.mystate != 'pre-natted':
                # start pre-natted timer
                self.start_time = bttime()

        if new_state != self.mystate:
            #print 'changing state from', self.mystate, 'to', new_state
            self.mystate = new_state
            self.change_state()

    def change_state(self):
        pass


import gtk

class GtkStatusLight(gtk.EventBox, StatusLight):

    def __init__(self, main):
        gtk.EventBox.__init__(self)
        StatusLight.__init__(self)
        self.main = main
        self.image = None
        self.images = {}
        for k,(s,t) in self.states.items():
            i = gtk.Image()
            i.set_from_stock(s, gtk.ICON_SIZE_LARGE_TOOLBAR)
            i.show()
            self.images[k] = i        
        self.set_size_request(24,24)
        self.main.tooltips.set_tip(self, 'tooltip')
        self.send_message('stop')

    def change_state(self):
        state = self.mystate
        assert self.states.has_key(state)
        if self.image is not None:
            self.remove(self.image)
        self.image = self.images[state]
        self.add(self.image)
        stock, tooltip = self.states[state]
        self.main.tooltips.set_tip(self, tooltip)