Package sysmon :: Module gui
[hide private]
[frames] | no frames]

Source Code for Module sysmon.gui

  1  ######################################################################### 
  2  # YASMon - Yet Another System Monitor                                   # 
  3  # Copyright (C) 2010  Scott Lawrence                                    # 
  4  #                                                                       # 
  5  # This program is free software: you can redistribute it and/or modify  # 
  6  # it under the terms of the GNU General Public License as published by  # 
  7  # the Free Software Foundation, either version 3 of the License, or     # 
  8  # (at your option) any later version.                                   # 
  9  #                                                                       # 
 10  # This program is distributed in the hope that it will be useful,       # 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of        # 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         # 
 13  # GNU General Public License for more details.                          # 
 14  #                                                                       # 
 15  # You should have received a copy of the GNU General Public License     # 
 16  # along with this program.  If not, see <http://www.gnu.org/licenses/>. # 
 17  ######################################################################### 
 18   
 19  """Provides a framework for a graphical user interface to YASMon, 
 20  using Qt4. 
 21   
 22  """ 
 23   
 24  #GUI Code for YASMon client (uses QT4) 
 25  from PyQt4.QtCore import * 
 26  from PyQt4.QtGui import * 
 27  from PyQt4 import QtSvg 
 28   
 29  import re,sys,sysmon,traceback 
 30   
31 -def yasmon_error(error):
32 """Displays the appropriate error message, based on the given 33 error object. 34 """ 35 #FIXME ibus issues and segfault 36 em=QErrorMessage() 37 tb=traceback.format_exc() 38 tb=re.sub(" ","&nbsp;&nbsp;&nbsp;&nbsp;",tb) 39 em.showMessage( 40 "<html><p>%s</p><p><b>Backtrace:</b></p>%s</html>" 41 % (error,re.sub("\n","<br />",tb))) 42 em.exec_()
43
44 -def about_yasmon(parent):
45 """Displays an "About YASMon" dialog box. 46 """ 47 dialog=AboutYasmon(parent) 48 dialog.exec_()
49
50 -def yasmon_icon():
51 """Returns a scalable version of YASMon's icon. 52 """ 53 return QIcon("/usr/share/icons/hicolor/scalable/apps/yasmon.svg")
54
55 -def yasmon_image():
56 """Returns an QSvgWidget with YASMon's logo 57 """ 58 i=QtSvg.QSvgWidget("/usr/share/icons/hicolor/scalable/apps/yasmon.svg") 59 i.setMaximumSize(i.sizeHint()) 60 i.setMinimumSize(i.sizeHint()) 61 return i
62
63 -def qt_icon():
64 """Returns a scalable version of QT's logo. 65 """ 66 return QIcon()
67
68 -class AboutYasmon(QDialog):
69 """YASMon's about dialog box. 70 """
71 - def __init__(self,parent):
72 super(AboutYasmon, self).__init__(parent) 73 self.setWindowTitle("About YASMon") 74 overlayout=QVBoxLayout() 75 layout=QHBoxLayout() 76 layout.addWidget(yasmon_image()) 77 sublayout=QVBoxLayout() 78 sublayout.addWidget(QLabel("<html><b>"+ 79 "Yet Another System Monitor</b></html>")) 80 sublayout.addWidget(QLabel("<html><p>Version %s</p>" % sysmon.version() 81 +"<p>&copy; 2010 Scott Lawrence " 82 +"&lt;<a href='mailto:bytbox@gmail.com'>" 83 +"bytbox@gmail.com</a>&gt;</p>" 84 +"<p>Licensed under the GNU GPL version 3 " 85 +"or, at your <br />choice, any later " 86 +"version.</p></html>")) 87 layout.addLayout(sublayout) 88 overlayout.addLayout(layout) 89 bb=QDialogButtonBox(QDialogButtonBox.Ok,Qt.Horizontal,self) 90 bb.setCenterButtons(True) 91 bb.accepted.connect(self.accept) 92 overlayout.addWidget(bb) 93 self.setLayout(overlayout)
94 95
96 -class ScaleView(QWidget):
97 """A widget to view information on a scale, with details 98 below. 99 100 """
101 - def __init__(self,name,min=0,max=100,unit='%',default=0):
102 QWidget.__init__(self) 103 self.name=name 104 self.min=min 105 self.max=max 106 self._value=default 107 self.unit=unit 108 self.setToolTip("%d/%d %s" % (int(self.value()),int(max),unit)) 109 self.setMaximumSize(QSize(70,100)) 110 self.setMinimumSize(QSize(70,100))
111
112 - def value(self):
113 """Returns the current value. 114 """ 115 return self._value
116
117 - def set_max(self,maxval):
118 """Sets the maximum value. 119 """ 120 self.max=maxval
121 - def set_min(self,minval):
122 """Sets the minimum value. 123 """ 124 self.min=minval
125
126 - def set_value(self,value):
127 """Sets the value to be displayed. 128 129 This method sets the value stored in the object and 130 updates the onscreen representation. 131 """ 132 self._value=value 133 self.setToolTip("%d/%d %s" % (int(self.value()),int(self.max),self.unit)) 134 self.update()
135
136 - def paintEvent(self,event):
137 #settings 138 painter=QPainter(self) 139 painter.setPen(QPen()) 140 painter.setBrush(QBrush()) 141 142 #draw the scale 143 painter.drawRect(QRect(7,0,56,64)) 144 height=(float(self.value())-self.min)*64.0/self.max 145 painter.fillRect(QRect(7,64,56,-height),QColor.fromRgb(height*3.9,0,0)) 146 #draw the text 147 painter.drawText(QRect(0,0,70,100), 148 Qt.AlignHCenter | Qt.AlignBottom, 149 self.name+"\n"+str(float(int((self.value()-self.min)*1000.0/self.max))/10)+'%')
150 151
152 - def sizeHint(self):
153 return QSize(70,100)
154 155 156
157 -class CPUView(ScaleView):
158 """A widget to view cpu usage information et al. for a single 159 CPU. 160 161 This consists of a simple graphic, with a single vertical 162 "progress bar" (labelled as appropriate) and two numbers 163 below: the exact percentage usage and the current temperature, 164 if available. 165 166 Although this view is meant for a single CPU, it may actually 167 represent multiple CPUs, depending on the implementation of 168 the backend object. 169 """
170 - def __init__(self,processor):
171 ScaleView.__init__(self,processor.name(),0,1,"MHz used") 172 self.processor=processor 173 #add me to the hook 174 processor.system().callback().hook("processor.%s.updated" % processor.name() 175 ,self.catch_update)
176
177 - def catch_update(self,processor):
178 self.set_max(self.processor.max_freq()) 179 self.set_value(self.processor.usage())
180 181
182 -class ProcessorView(QWidget):
183 """A widget to view processor information for multiple 184 processors. 185 186 This will normally be significantly wider than it is tall, as 187 it consists simply of a horizontal row of CPUViews. 188 """
189 - def __init__(self,processorlist):
190 QWidget.__init__(self) 191 layout=QHBoxLayout() 192 layout.setMargin(0) 193 self.setLayout(layout) 194 #for each cpu... 195 for processor in processorlist: 196 layout.addWidget(CPUView(processor))
197
198 -class MemoryView(ScaleView):
199 """A widget to display the current memory usage in a memory 200 bank (RAM). 201 202 """
203 - def __init__(self,memory):
204 ScaleView.__init__(self,"ram",0,1,'MB') 205 self.memory=memory 206 memory.system().callback().hook('memory.updated',self.catch_update)
207
208 - def catch_update(self,data):
209 self.set_max(self.memory.total_memory()/1000000) 210 self.set_value(self.memory.active_memory()/1000000)
211
212 -class UptimeView(QLabel):
213 """A widget to display the current system uptime. 214 """
215 - def __init__(self,uptime):
216 QLabel.__init__(self) 217 self.uptime=uptime 218 self.setAlignment(Qt.AlignCenter) 219 uptime.system().callback().hook('uptime.updated',self.catch_update)
220
221 - def catch_update(self,data):
222 uptime=int(self.uptime.uptime()) 223 days=uptime/(60*60*24) 224 hours=(uptime/(60*60))%24 225 mins=((uptime/60)%60) 226 secs=uptime%60 227 self.setText("Up %d days, %02d:%02d:%02d" % (days,hours,mins,secs))
228
229 - def sizeHint(self):
230 return QSize(120,20)
231
232 -class SystemView(QGroupBox):
233 """Displays current information for the most general (and 234 critical) parts of a single system. 235 236 This generally means the processors, memory, and hard disk 237 usage. 238 """
239 - def __init__(self,system):
240 QFrame.__init__(self,system.name()) 241 overlayout=QVBoxLayout() 242 layout=QHBoxLayout() 243 self.setLayout(overlayout) 244 overlayout.addWidget(UptimeView(system.uptime())) 245 overlayout.addSpacing(10) 246 overlayout.addLayout(layout) 247 layout.addWidget(ProcessorView(system.processors())) 248 layout.addSpacing(16) 249 layout.addWidget(MemoryView(system.memory()))
250
251 -class HistoryView(QFrame):
252 """Displays most of OverviewView's content, as a history. 253 254 This view consists of a set of a few graphs, each containing in 255 somewhat condensed for the history of some measure of 256 performance. In general, single pixel is used for every related 257 update fired. 258 """
259 - def __init__(self,system):
260 QFrame.__init__(self)
261
262 -class TopView(QFrame):
263 """Displays a top-like view of a system. 264 """
265 - def __init__(self,system):
266 QFrame.__init__(self)
267
268 -class DetailedSystemView(QFrame):
269 """Displays a detailed system view, consisting of a HistoryView 270 and a TopView. 271 """
272 - def __init__(self,system):
273 QFrame.__init__(self)
274
275 -class MainView(QWidget):
276 - def __init__(self,systems):
277 QWidget.__init__(self) 278 layout=QVBoxLayout() 279 sublayout=QHBoxLayout() 280 self.setLayout(layout) 281 tabWidget=QTabWidget() 282 tabWidget.setTabPosition(QTabWidget.South) 283 for system in systems: 284 tabid=tabWidget.addTab(DetailedSystemView(systems[system]),QString(system)) 285 tabWidget.setTabToolTip(tabid,QString("View information for %s" % system)) 286 #FIXME - set icon 287 sublayout.addWidget(SystemView(systems[system])) 288 layout.addLayout(sublayout) 289 layout.addWidget(tabWidget)
290