~ubuntu-branches/ubuntu/quantal/lptools/quantal

« back to all changes in this revision

Viewing changes to bin/lp-review-list

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij, Robert Collins, Jelmer Vernooij
  • Date: 2011-09-01 22:47:11 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20110901224711-05u7hwne9anexqq9
Tags: 0.0.1~bzr28-1
[ Robert Collins ]
* Control tweaks.

[ Jelmer Vernooij ]
* New upstream snapshot.
 + Imports a few tools from ubuntu-dev-tools. Breaks/Replaces added.
* Add myself to Uploaders.
* Bump standards version to 3.9.2 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
#
 
3
# Author: Rodney Dawes <rodney.dawes@canonical.com>
 
4
#
 
5
# Copyright 2009 Canonical Ltd.
 
6
#
 
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.
 
10
#
 
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.
 
15
#
 
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/>.
 
18
 
 
19
from __future__ import with_statement
 
20
import re
 
21
import subprocess
 
22
from threading import Thread
 
23
 
 
24
import pygtk
 
25
pygtk.require('2.0')
 
26
import gobject
 
27
import gtk
 
28
 
 
29
from lptools import config
 
30
 
 
31
VOTES = { "Approve" : "#00ff00",
 
32
          "Needs Fixing" : "#993300",
 
33
          "Disapprove" : "#ff0000",
 
34
          "Resubmit" : "#ff0000",
 
35
          "Pending" : "#ff6600",
 
36
          "Abstain" : "#909090",
 
37
          "Needs Information" : "#909090",
 
38
          }
 
39
 
 
40
class Window(gtk.Window):
 
41
 
 
42
      def __init__(self):
 
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())
 
48
 
 
49
            vbox = gtk.VBox()
 
50
            self.add(vbox)
 
51
            vbox.show()
 
52
 
 
53
            toolbar = gtk.Toolbar()
 
54
            vbox.pack_start(toolbar, expand=False, fill=False)
 
55
            toolbar.show()
 
56
 
 
57
            button = gtk.ToolButton(gtk.STOCK_REFRESH)
 
58
            button.connect("clicked", self.__refresh)
 
59
            toolbar.insert(button, -1);
 
60
            button.show()
 
61
 
 
62
            scrollwin = gtk.ScrolledWindow()
 
63
            scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
 
64
            vbox.pack_start(scrollwin, expand=True, fill=True)
 
65
            scrollwin.show()
 
66
 
 
67
            self.store = gtk.ListStore(str, str)
 
68
 
 
69
            view = gtk.TreeView(self.store)
 
70
            view.connect("row-activated", self.__open_link)
 
71
            scrollwin.add(view)
 
72
            view.show()
 
73
 
 
74
            cell = gtk.CellRendererText()
 
75
            col = gtk.TreeViewColumn("Branch", cell, markup=0)
 
76
            view.append_column(col)
 
77
 
 
78
            self.launchpad = None
 
79
            self.me = None
 
80
 
 
81
            self.thread = None
 
82
            self.id = 0
 
83
            Thread(target=self.__lp_login).start()
 
84
 
 
85
      def __lp_login(self):
 
86
            self.launchpad = config.get_launchpad("review-list")
 
87
 
 
88
            self.me = self.launchpad.me
 
89
 
 
90
            print "Allo, %s" % self.me.name
 
91
            gtk.gdk.threads_enter()
 
92
            self.__refresh(None)
 
93
            gtk.gdk.threads_leave()
 
94
            return False
 
95
 
 
96
      def __refresh(self, button, data=None):
 
97
            if self.id != 0:
 
98
                  gobject.source_remove(self.id)
 
99
                  self.id = 0
 
100
            self.__timeout()
 
101
            self.id = gobject.timeout_add_seconds(5 * 60, self.__timeout)
 
102
            return False
 
103
 
 
104
      def __open_link(self, view, path, column, data=None):
 
105
            row = self.store.get_iter(path)
 
106
            url, = self.store.get(row, 1)
 
107
            if url == "":
 
108
                  return
 
109
            ret = subprocess.call(["xdg-open", url])
 
110
            if ret != 0:
 
111
                  dialog = gtk.MessageDialog(self, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Failed to run 'xdg-open %s'\n" % url)
 
112
                  dialog.run()
 
113
                  dialog.destroy()
 
114
 
 
115
      def __load_merges(self):
 
116
            merges = []
 
117
            mine = self.me.getRequestedReviews(status=[u'Needs review'])
 
118
            for merge in mine:
 
119
                  merges.append(merge)
 
120
 
 
121
            for team in self.me.super_teams:
 
122
                  for merge in team.getRequestedReviews(status=[u'Needs review']):
 
123
                        if merge not in merges:
 
124
                              merges.append(merge)
 
125
 
 
126
            for merge in merges:
 
127
                  votes = {}
 
128
                  for key in VOTES.keys():
 
129
                        votes[key] = 0
 
130
 
 
131
                  for vote in merge.votes:
 
132
                        if not vote.comment:
 
133
                              continue
 
134
                        else:
 
135
                              votes[vote.comment.vote] += 1
 
136
 
 
137
                  for key in votes.keys():
 
138
                        if votes[key] == 0:
 
139
                              votes.pop(key, None)
 
140
 
 
141
                  vstr = ", ".join(
 
142
                        ["<span color='%s'>%s</span>: %d" \
 
143
                               % (VOTES[key], key, votes[key]) \
 
144
                               for key in votes.keys()]
 
145
                        )
 
146
                  if vstr == "":
 
147
                        vstr = "No Reviews"
 
148
                  status = "%s\n%s" % (merge.source_branch.display_name,
 
149
                                       vstr)
 
150
                  urlp = re.compile(
 
151
                        'http[s]?://api\.(.*)launchpad\.net/[^/]+/')
 
152
                  merge_url = urlp.sub(
 
153
                        'http://launchpad.net/', merge.self_link)
 
154
 
 
155
                  gtk.gdk.threads_enter()
 
156
                  self.store.append((status, merge_url))
 
157
                  gtk.gdk.threads_leave()
 
158
            
 
159
      def __timeout(self):
 
160
            self.store.clear()
 
161
            if self.thread and self.thread.isAlive():
 
162
                  return True
 
163
 
 
164
            if self.thread is None:
 
165
                  thread = Thread(target=self.__load_merges)
 
166
 
 
167
            thread.start()
 
168
            return True
 
169
 
 
170
if __name__ == "__main__":
 
171
      gobject.threads_init()
 
172
      gtk.gdk.threads_init()
 
173
      try:
 
174
            win = Window()
 
175
            win.show()
 
176
            gtk.gdk.threads_enter()
 
177
            gtk.main()
 
178
            gtk.gdk.threads_leave()
 
179
      except KeyboardInterrupt:
 
180
            gtk.main_quit()
 
181