3
# Author: Rodney Dawes <rodney.dawes@canonical.com>
5
# Copyright 2009 Canonical Ltd.
7
# This program is free software: you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License version 3, as published
9
# by the Free Software Foundation.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranties of
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
# PURPOSE. See the GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License along
17
# with this program. If not, see <http://www.gnu.org/licenses/>.
19
from __future__ import with_statement
22
from threading import Thread
29
from lptools import config
31
VOTES = { "Approve" : "#00ff00",
32
"Needs Fixing" : "#993300",
33
"Disapprove" : "#ff0000",
34
"Resubmit" : "#ff0000",
35
"Pending" : "#ff6600",
36
"Abstain" : "#909090",
37
"Needs Information" : "#909090",
40
class Window(gtk.Window):
43
gtk.Window.__init__(self)
44
self.set_title("Pending Reviews")
45
self.set_default_size(320, 400)
46
self.connect("destroy", lambda w: gtk.main_quit())
47
self.connect("delete_event", lambda w,x: gtk.main_quit())
53
toolbar = gtk.Toolbar()
54
vbox.pack_start(toolbar, expand=False, fill=False)
57
button = gtk.ToolButton(gtk.STOCK_REFRESH)
58
button.connect("clicked", self.__refresh)
59
toolbar.insert(button, -1);
62
scrollwin = gtk.ScrolledWindow()
63
scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
64
vbox.pack_start(scrollwin, expand=True, fill=True)
67
self.store = gtk.ListStore(str, str)
69
view = gtk.TreeView(self.store)
70
view.connect("row-activated", self.__open_link)
74
cell = gtk.CellRendererText()
75
col = gtk.TreeViewColumn("Branch", cell, markup=0)
76
view.append_column(col)
83
Thread(target=self.__lp_login).start()
86
self.launchpad = config.get_launchpad("review-list")
88
self.me = self.launchpad.me
90
print "Allo, %s" % self.me.name
91
gtk.gdk.threads_enter()
93
gtk.gdk.threads_leave()
96
def __refresh(self, button, data=None):
98
gobject.source_remove(self.id)
101
self.id = gobject.timeout_add_seconds(5 * 60, self.__timeout)
104
def __open_link(self, view, path, column, data=None):
105
row = self.store.get_iter(path)
106
url, = self.store.get(row, 1)
109
ret = subprocess.call(["xdg-open", url])
111
dialog = gtk.MessageDialog(self, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Failed to run 'xdg-open %s'\n" % url)
115
def __load_merges(self):
117
mine = self.me.getRequestedReviews(status=[u'Needs review'])
121
for team in self.me.super_teams:
122
for merge in team.getRequestedReviews(status=[u'Needs review']):
123
if merge not in merges:
128
for key in VOTES.keys():
131
for vote in merge.votes:
135
votes[vote.comment.vote] += 1
137
for key in votes.keys():
142
["<span color='%s'>%s</span>: %d" \
143
% (VOTES[key], key, votes[key]) \
144
for key in votes.keys()]
148
status = "%s\n%s" % (merge.source_branch.display_name,
151
'http[s]?://api\.(.*)launchpad\.net/[^/]+/')
152
merge_url = urlp.sub(
153
'http://launchpad.net/', merge.self_link)
155
gtk.gdk.threads_enter()
156
self.store.append((status, merge_url))
157
gtk.gdk.threads_leave()
161
if self.thread and self.thread.isAlive():
164
if self.thread is None:
165
thread = Thread(target=self.__load_merges)
170
if __name__ == "__main__":
171
gobject.threads_init()
172
gtk.gdk.threads_init()
176
gtk.gdk.threads_enter()
178
gtk.gdk.threads_leave()
179
except KeyboardInterrupt: