statusview.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 ######################################################################
3 #
4 # Name: statusview.py
5 #
6 # Purpose: Python class StatusView is a widget for displaying
7 # project status information.
8 #
9 # Created: 22-Jan-2015 Herbert Greenlee
10 #
11 ######################################################################
12 
13 from __future__ import absolute_import
14 from __future__ import print_function
15 import sys, traceback
16 from project_modules.projectstatus import ProjectStatus
17 from project_modules.batchstatus import BatchStatus
18 
19 # Import GUI stuff
20 
21 # Import Tkinter GUI stuff
22 
23 try:
24  import tkinter as tk
25  import tkinter.messagebox as tkinter_messagebox
26  import tkinter.font as tkinter_font
27 except ImportError:
28  import Tkinter as tk
29  import tkMessageBox as tkinter_messagebox
30  import tkFont as tkinter_font
31 
32 # Make symbolic names for column indices.
33 
34 kEXISTS = 1
35 kNFILE = 2
36 kNEV = 3
37 kNANA = 4
38 kNERROR = 5
39 kNMISS = 6
40 kIDLE = 7
41 kRUNNING = 8
42 kHELD = 9
43 kOTHER = 10
44 kEND = 11
45 
46 # Project widget class
47 
48 class ProjectStatusView(tk.Frame):
49 
50  # Constructor.
51 
52  def __init__(self, parent, project_defs=[]):
53 
54 
55  self.parent = parent
56  self.project_defs = project_defs
57 
58  # Register our outermost frame in the parent window.
59 
60  tk.Frame.__init__(self, self.parent)
61  self.pack(expand=1, fill=tk.BOTH)
62  self.rowconfigure(0, weight=1)
63 
64  # Dictionaries to hold stage widgets.
65 
67  self.exists_labels = {}
68  self.nfile_labels = {}
69  self.nev_labels = {}
70  self.nana_labels = {}
71  self.nerror_labels = {}
72  self.nmiss_labels = {}
73  self.nidle_labels = {}
74  self.nrunning_labels = {}
75  self.nheld_labels = {}
76  self.nother_labels = {}
77 
78  # Make widgets that belong to this widget.
79 
80  self.make_widgets()
81  if len(self.project_defs) > 0:
82  self.update_status()
83 
84  # Make widgets.
85 
86  def make_widgets(self):
87 
88  # Add column category headings.
89 
90  self.stage_cat = tk.Label(self, bg='powderblue', relief=tk.RIDGE, text='',
91  padx=10, pady=10, font=tkinter_font.Font(size=12))
92  self.stage_cat.grid(row=0, column=0, sticky=tk.N+tk.E+tk.W+tk.S)
93  self.files_cat = tk.Frame(self, bd=1, relief=tk.SUNKEN, bg='lightsteelblue')
94  files_label = tk.Label(self.files_cat, bg='lightsteelblue', relief=tk.FLAT, text='Output',
95  padx=10, font=tkinter_font.Font(size=12))
96  files_label.pack(side=tk.LEFT, expand=1, fill=tk.BOTH)
97  fetchlog_button = tk.Button(self.files_cat, bg='lightcyan', activebackground='aliceblue',
98  text='Fetchlog', command=self.parent.parent.fetchlog)
99  fetchlog_button.pack(side=tk.RIGHT)
100  checkana_button = tk.Button(self.files_cat, bg='lightcyan', activebackground='aliceblue',
101  text='CheckAna', command=self.parent.parent.checkana)
102  checkana_button.pack(side=tk.RIGHT)
103  check_button = tk.Button(self.files_cat, bg='lightcyan', activebackground='aliceblue',
104  text='Check', command=self.parent.parent.check)
105  check_button.pack(side=tk.RIGHT)
106  self.files_cat.grid(row=0, column=kEXISTS, columnspan=kIDLE-kEXISTS,
107  sticky=tk.N+tk.E+tk.W+tk.S)
108  self.batch_cat = tk.Frame(self, bd=1, relief=tk.SUNKEN, bg='powderblue')
109  batch_label = tk.Label(self.batch_cat, bg='powderblue', relief=tk.FLAT, text='Batch Jobs',
110  padx=10, font=tkinter_font.Font(size=12))
111  batch_label.pack(side=tk.LEFT, expand=1, fill=tk.BOTH)
112  batch_button = tk.Button(self.batch_cat, bg='lightcyan', activebackground='aliceblue',
113  text='Update', command=self.update_jobs)
114  batch_button.pack(side=tk.RIGHT)
115  makeup_button = tk.Button(self.batch_cat, bg='lightcyan', activebackground='aliceblue',
116  text='Makeup', command=self.parent.parent.makeup)
117  makeup_button.pack(side=tk.RIGHT)
118  submit_button = tk.Button(self.batch_cat, bg='lightcyan', activebackground='aliceblue',
119  text='Submit', command=self.parent.parent.submit)
120  submit_button.pack(side=tk.RIGHT)
121  self.batch_cat.grid(row=0, column=kIDLE, columnspan=kEND-kIDLE,
122  sticky=tk.N+tk.E+tk.W+tk.S)
123 
124  # Add column headings.
125 
126  self.stage_head = tk.Label(self, bg='powderblue', relief=tk.RIDGE, text='Stage',
127  padx=10, pady=10, font=tkinter_font.Font(size=12))
128  self.stage_head.grid(row=1, column=0, sticky=tk.N+tk.E+tk.W+tk.S)
129  self.columnconfigure(0, weight=1)
130  self.exists_head = tk.Label(self, bg='lightsteelblue', relief=tk.RIDGE, text='Exists?',
131  padx=10, font=tkinter_font.Font(size=12))
132  self.exists_head.grid(row=1, column=kEXISTS, sticky=tk.N+tk.E+tk.W+tk.S)
133  self.columnconfigure(kEXISTS, weight=1)
134  self.nfile_head = tk.Label(self, bg='lightsteelblue', relief=tk.RIDGE, text='Art Files',
135  padx=10, font=tkinter_font.Font(size=12))
136  self.nfile_head.grid(row=1, column=kNFILE, sticky=tk.N+tk.E+tk.W+tk.S)
137  self.columnconfigure(kNFILE, weight=1)
138  self.nev_head = tk.Label(self, bg='lightsteelblue', relief=tk.RIDGE, text='Events',
139  padx=10, font=tkinter_font.Font(size=12))
140  self.nev_head.grid(row=1, column=kNEV, sticky=tk.N+tk.E+tk.W+tk.S)
141  self.columnconfigure(kNANA, weight=1)
142  self.nana_head = tk.Label(self, bg='lightsteelblue', relief=tk.RIDGE, text='Ana Files',
143  padx=10, font=tkinter_font.Font(size=12))
144  self.nana_head.grid(row=1, column=kNANA, sticky=tk.N+tk.E+tk.W+tk.S)
145  self.columnconfigure(kNANA, weight=1)
146  self.nerror_head = tk.Label(self, bg='lightsteelblue', relief=tk.RIDGE, text='Errors',
147  padx=10, font=tkinter_font.Font(size=12))
148  self.nerror_head.grid(row=1, column=kNERROR, sticky=tk.N+tk.E+tk.W+tk.S)
149  self.columnconfigure(kNERROR, weight=1)
150  self.miss_head = tk.Label(self, bg='lightsteelblue', relief=tk.RIDGE, text='Missing',
151  padx=10, font=tkinter_font.Font(size=12))
152  self.miss_head.grid(row=1, column=kNMISS, sticky=tk.N+tk.E+tk.W+tk.S)
153  self.columnconfigure(kNMISS, weight=1)
154  self.idle_head = tk.Label(self, bg='powderblue', relief=tk.RIDGE, text='Idle',
155  padx=10, font=tkinter_font.Font(size=12))
156  self.idle_head.grid(row=1, column=kIDLE, sticky=tk.N+tk.E+tk.W+tk.S)
157  self.columnconfigure(kIDLE, weight=1)
158  self.running_head = tk.Label(self, bg='powderblue', relief=tk.RIDGE, text='Running',
159  padx=10, font=tkinter_font.Font(size=12))
160  self.running_head.grid(row=1, column=kRUNNING, sticky=tk.N+tk.E+tk.W+tk.S)
161  self.columnconfigure(kRUNNING, weight=1)
162  self.held_head = tk.Label(self, bg='powderblue', relief=tk.RIDGE, text='Held',
163  padx=10, font=tkinter_font.Font(size=12))
164  self.held_head.grid(row=1, column=kHELD, sticky=tk.N+tk.E+tk.W+tk.S)
165  self.columnconfigure(kHELD, weight=1)
166  self.other_head = tk.Label(self, bg='powderblue', relief=tk.RIDGE, text='Other',
167  padx=10, font=tkinter_font.Font(size=12))
168  self.other_head.grid(row=1, column=kOTHER, sticky=tk.N+tk.E+tk.W+tk.S)
169  self.columnconfigure(kOTHER, weight=1)
170 
171  # Set or update project definition.
172 
173  def set_project(self, project_defs):
174  self.project_defs = project_defs
175  self.update_status()
176 
177  # Update status display.
178 
179  def update_status(self):
180 
181  top=self.winfo_toplevel()
182  old_cursor = top['cursor']
183  try:
184  top['cursor'] = 'watch'
185  top.update_idletasks()
186  ps = ProjectStatus(self.project_defs)
187  bs = BatchStatus(self.project_defs)
188  top['cursor'] = old_cursor
189  except:
190  top['cursor'] = old_cursor
191  e = sys.exc_info()
192  traceback.print_tb(e[2])
193  tkinter_messagebox.showerror('', e[1])
194 
195  # Update label widgets.
196 
197  for key in list(self.stage_name_labels.keys()):
198  self.stage_name_labels[key].grid_forget()
199  for key in list(self.exists_labels.keys()):
200  self.exists_labels[key].grid_forget()
201  for key in list(self.nfile_labels.keys()):
202  self.nfile_labels[key].grid_forget()
203  for key in list(self.nev_labels.keys()):
204  self.nev_labels[key].grid_forget()
205  for key in list(self.nana_labels.keys()):
206  self.nana_labels[key].grid_forget()
207  for key in list(self.nerror_labels.keys()):
208  self.nerror_labels[key].grid_forget()
209  for key in list(self.nmiss_labels.keys()):
210  self.nmiss_labels[key].grid_forget()
211  for key in list(self.nidle_labels.keys()):
212  self.nidle_labels[key].grid_forget()
213  for key in list(self.nrunning_labels.keys()):
214  self.nrunning_labels[key].grid_forget()
215  for key in list(self.nheld_labels.keys()):
216  self.nheld_labels[key].grid_forget()
217  for key in list(self.nother_labels.keys()):
218  self.nother_labels[key].grid_forget()
219 
220  row = 1
221  for project_def in self.project_defs:
222  for stage in project_def.stages:
223  row = row + 1
224  ss = ps.get_stage_status(stage.name)
225  bss = bs.get_stage_status(stage.name)
226 
227  if stage.name not in self.stage_name_labels:
228  self.stage_name_labels[stage.name] = tk.Label(self, bg='powderblue',
229  relief=tk.RIDGE,
230  padx=10, pady=5,
231  font=tkinter_font.Font(size=12))
232  self.stage_name_labels[stage.name]['text'] = stage.name
233  self.stage_name_labels[stage.name].bind('<Button-1>', self.click_stage)
234  self.stage_name_labels[stage.name].grid(row=row, column=0,
235  sticky=tk.N+tk.E+tk.W+tk.S)
236  self.rowconfigure(row, weight=1)
237 
238  if stage.name not in self.exists_labels:
239  self.exists_labels[stage.name] = tk.Label(self, bg='aliceblue', relief=tk.RIDGE,
240  font=tkinter_font.Font(size=12))
241  if ss.exists:
242  self.exists_labels[stage.name]['text'] = 'Yes'
243  self.exists_labels[stage.name]['fg'] = 'black'
244  else:
245  self.exists_labels[stage.name]['text'] = 'No'
246  self.exists_labels[stage.name]['fg'] = 'red'
247  self.exists_labels[stage.name].grid(row=row, column=kEXISTS,
248  sticky=tk.N+tk.E+tk.W+tk.S)
249  self.rowconfigure(row, weight=1)
250 
251  if stage.name not in self.nfile_labels:
252  self.nfile_labels[stage.name] = tk.Label(self, bg='aliceblue', relief=tk.RIDGE,
253  font=tkinter_font.Font(size=12))
254  self.nfile_labels[stage.name]['text'] = str(ss.nfile)
255  self.nfile_labels[stage.name].grid(row=row, column=kNFILE,
256  sticky=tk.N+tk.E+tk.W+tk.S)
257  self.rowconfigure(row, weight=1)
258 
259  if stage.name not in self.nev_labels:
260  self.nev_labels[stage.name] = tk.Label(self, bg='aliceblue', relief=tk.RIDGE,
261  font=tkinter_font.Font(size=12))
262  self.nev_labels[stage.name]['text'] = str(ss.nev)
263  self.nev_labels[stage.name].grid(row=row, column=kNEV, sticky=tk.N+tk.E+tk.W+tk.S)
264  self.rowconfigure(row, weight=1)
265 
266  if stage.name not in self.nana_labels:
267  self.nana_labels[stage.name] = tk.Label(self, bg='aliceblue', relief=tk.RIDGE,
268  font=tkinter_font.Font(size=12))
269  self.nana_labels[stage.name]['text'] = str(ss.nana)
270  self.nana_labels[stage.name].grid(row=row, column=kNANA, sticky=tk.N+tk.E+tk.W+tk.S)
271  self.rowconfigure(row, weight=1)
272 
273  if stage.name not in self.nerror_labels:
274  self.nerror_labels[stage.name] = tk.Label(self, bg='aliceblue', relief=tk.RIDGE,
275  font=tkinter_font.Font(size=12))
276  self.nerror_labels[stage.name]['text'] = str(ss.nerror)
277  if ss.nerror == 0:
278  self.nerror_labels[stage.name]['fg'] = 'black'
279  else:
280  self.nerror_labels[stage.name]['fg'] = 'red'
281  self.nerror_labels[stage.name].grid(row=row, column=kNERROR,
282  sticky=tk.N+tk.E+tk.W+tk.S)
283  self.rowconfigure(row, weight=1)
284 
285  if stage.name not in self.nmiss_labels:
286  self.nmiss_labels[stage.name] = tk.Label(self, bg='aliceblue', relief=tk.RIDGE,
287  font=tkinter_font.Font(size=12))
288  self.nmiss_labels[stage.name]['text'] = str(ss.nmiss)
289  if ss.nmiss == 0:
290  self.nmiss_labels[stage.name]['fg'] = 'black'
291  else:
292  self.nmiss_labels[stage.name]['fg'] = 'red'
293  self.nmiss_labels[stage.name].grid(row=row, column=kNMISS,
294  sticky=tk.N+tk.E+tk.W+tk.S)
295  self.rowconfigure(row, weight=1)
296 
297  if stage.name not in self.nidle_labels:
298  self.nidle_labels[stage.name] = tk.Label(self, bg='lightcyan', relief=tk.RIDGE,
299  font=tkinter_font.Font(size=12))
300  self.nidle_labels[stage.name]['text'] = bss[0]
301  self.nidle_labels[stage.name].grid(row=row, column=kIDLE,
302  sticky=tk.N+tk.E+tk.W+tk.S)
303  self.rowconfigure(row, weight=1)
304 
305  if stage.name not in self.nrunning_labels:
306  self.nrunning_labels[stage.name] = tk.Label(self, bg='lightcyan',
307  relief=tk.RIDGE,
308  font=tkinter_font.Font(size=12))
309  self.nrunning_labels[stage.name]['text'] = bss[1]
310  self.nrunning_labels[stage.name].grid(row=row,
311  column=kRUNNING, sticky=tk.N+tk.E+tk.W+tk.S)
312  self.rowconfigure(row, weight=1)
313 
314  if stage.name not in self.nheld_labels:
315  self.nheld_labels[stage.name] = tk.Label(self, bg='lightcyan', relief=tk.RIDGE,
316  font=tkinter_font.Font(size=12))
317  self.nheld_labels[stage.name]['text'] = bss[2]
318  self.nheld_labels[stage.name].grid(row=row, column=kHELD,
319  sticky=tk.N+tk.E+tk.W+tk.S)
320  self.rowconfigure(row, weight=1)
321 
322  if stage.name not in self.nother_labels:
323  self.nother_labels[stage.name] = tk.Label(self, bg='lightcyan', relief=tk.RIDGE,
324  font=tkinter_font.Font(size=12))
325  self.nother_labels[stage.name]['text'] = bss[3]
326  self.nother_labels[stage.name].grid(row=row, column=kOTHER,
327  sticky=tk.N+tk.E+tk.W+tk.S)
328  self.rowconfigure(row, weight=1)
329 
330 
331  # Highlight stage.
332 
333  def highlight_stage(self, stagename):
334  for key in list(self.stage_name_labels.keys()):
335  self.stage_name_labels[key]['bg'] = 'powderblue'
336  self.exists_labels[key]['bg'] = 'aliceblue'
337  self.nfile_labels[key]['bg'] = 'aliceblue'
338  self.nev_labels[key]['bg'] = 'aliceblue'
339  self.nana_labels[key]['bg'] = 'aliceblue'
340  self.nerror_labels[key]['bg'] = 'aliceblue'
341  self.nmiss_labels[key]['bg'] = 'aliceblue'
342  self.nidle_labels[key]['bg'] = 'lightcyan'
343  self.nrunning_labels[key]['bg'] = 'lightcyan'
344  self.nheld_labels[key]['bg'] = 'lightcyan'
345  self.nother_labels[key]['bg'] = 'lightcyan'
346  if stagename in self.stage_name_labels:
347  self.stage_name_labels[stagename]['bg'] = 'white'
348  self.exists_labels[stagename]['bg'] = 'white'
349  self.nfile_labels[stagename]['bg'] = 'white'
350  self.nev_labels[stagename]['bg'] = 'white'
351  self.nana_labels[stagename]['bg'] = 'white'
352  self.nerror_labels[stagename]['bg'] = 'white'
353  self.nmiss_labels[stagename]['bg'] = 'white'
354  self.nidle_labels[stagename]['bg'] = 'white'
355  self.nrunning_labels[stagename]['bg'] = 'white'
356  self.nheld_labels[stagename]['bg'] = 'white'
357  self.nother_labels[stagename]['bg'] = 'white'
358 
359  # Update jobs button.
360 
361  def update_jobs(self):
362  top=self.winfo_toplevel()
363  old_cursor = top['cursor']
364  try:
365  top['cursor'] = 'watch'
366  top.update_idletasks()
367  BatchStatus.update_jobs()
368  top['cursor'] = old_cursor
369  except:
370  top['cursor'] = old_cursor
371  e = sys.exc_info()
372  traceback.print_tb(e[2])
373  tkinter_messagebox.showerror('', e[1])
374  self.update_status()
375 
376  # Click on stage mouse event callback.
377 
378  def click_stage(self, event):
379  stagename = event.widget['text']
380 
381  # Choose stage in parent app.
382 
383  self.parent.parent.choose_stage(stagename)
def __init__(self, parent, project_defs=[])
Definition: statusview.py:52
def highlight_stage(self, stagename)
Definition: statusview.py:333
def set_project(self, project_defs)
Definition: statusview.py:173
static QCString str