1
# Copyright (C) 2008 onox <denkpadje@gmail.com>
3
# This program is free software: you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation, version 2 of the License.
7
# This program is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
# GNU General Public License for more details.
12
# You should have received a copy of the GNU General Public License
13
# along with this program. If not, see <http://www.gnu.org/licenses/>.
23
from awn.extras import AWNLib
26
from interfaces.sensor import Sensor
27
from interfaces.acpi import AcpiInterface
28
from interfaces.ibmacpi import IbmAcpiInterface
30
applet_name = "Sensors Monitor"
31
applet_version = "0.2.8"
32
applet_description = "An applet to monitor the various sensors in your system"
34
images_dir = os.path.join(os.path.dirname(__file__), "images")
36
# Logo of the applet, used as the applet's icon and shown in the GTK About dialog
37
applet_logo = os.path.join(images_dir, "sensors-applet.png")
39
# Interval in seconds between two successive updates of the sensors
40
update_sensors_interval = 2.0
43
Range in percents of difference between very high and very low temperature.
45
If, for example, the very high temperature is 60 C and the very low temperature
46
is 20 C, then the high temperature is 85 C minus 25%. Low temperature is 20 C
49
high_to_very_high_range = 25.0
50
very_low_to_low_range = 15.0
52
temperature_units = ["Celcius", "Fahrenheit", "Kelvin"]
54
interfaces = [AcpiInterface, IbmAcpiInterface]
58
FIXED 1) temperature unit kunnen uitlezen en opslaan
59
FIXED 2) weten welke unit een sensor heeft, en dat omrekenen naar de gewenste unit
60
3) ander plaatje kunnen kiezen (maar bij sommige sensoren moet het plaatje niet veranderbaar zijn)
61
4) alarm kunnen instellen, checken voor libnotify en notifyen als alarm afgaat
62
5) via dbus de cpufreq monitor met een algoritme downscalen als de temperature van de cpu high wordt
63
6) iets voor de titel en icon bedenken
64
7) meer backends toevoegen
69
""" An applet to monitor the various sensors in your system """
71
def __init__(self, applet):
74
applet.title.set("Sensors")
75
height = self.applet.get_height()
76
applet.icon.set(gdk.pixbuf_new_from_file_at_size(applet_logo, height, height), True)
78
self.active_interface = {}
79
for interface in interfaces:
80
print interface.name()
81
if interface.interface_useable():
82
self.active_interface[interface.name()] = interface(self.applet.settings)
84
self.setup_context_menu()
86
self.setup_main_dialog()
88
def setup_context_menu(self):
89
""" Creates a context menu to activate "Preferences" ("About" window
90
is created automatically by AWNLib) """
92
prefs = self.applet.dialog.new("preferences").vbox
94
notebook = gtk.Notebook()
95
notebook.set_border_width(6)
99
"update-interval": update_sensors_interval,
100
"temperature-unit": temperature_units[0]
102
self.applet.settings.load(default_values)
104
vbox_general = gtk.VBox(spacing=18)
105
vbox_general.set_border_width(12)
106
notebook.append_page(vbox_general, gtk.Label("General"))
108
vbox = AWNLib.create_frame(vbox_general, "Display")
109
# vbox_general.pack_start(frame, expand=False)
111
hbox = gtk.HBox(spacing=13)
114
label = gtk.Label("_Temperature unit:")
115
label.set_use_underline(True)
118
combobox = gtk.combo_box_new_text()
119
for unit in temperature_units:
120
combobox.append_text(unit)
121
combobox.set_active(temperature_units.index(self.applet.settings["temperature-unit"]))
122
combobox.connect("changed", self.changed_temperature_unit_cb)
127
vbox = AWNLib.create_frame(vbox_general, "Update")
128
# vbox_general.pack_start(frame, expand=False)
130
hbox = gtk.HBox(spacing=13)
133
label = gtk.Label("Update _interval (secs):")
134
label.set_use_underline(True)
137
adjustment = gtk.Adjustment(self.applet.settings["update-interval"], 1.5, 10, 0.5, 1.0) # TODO get value from settings
138
spin_button = gtk.SpinButton(adjustment, 0.5, 1)
139
spin_button.set_update_policy(gtk.UPDATE_IF_VALID)
140
spin_button.connect("value-changed", self.changed_update_interval_cb)
141
hbox.add(spin_button)
145
vbox = AWNLib.create_frame(vbox_general, "Notifications")
146
# vbox_general.pack_start(frame, expand=False)
148
# TODO connect signal
149
vbox.add(gtk.CheckButton("Display _notifications"))
151
vbox_sensors = gtk.VBox(spacing=18)
152
vbox_sensors.set_border_width(12)
153
notebook.append_page(vbox_sensors, gtk.Label("Sensors"))
155
self.sensors_store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN)
157
for if_name, interface in self.active_interface.iteritems():
158
parent = self.sensors_store.append(None, (None, if_name, None, None, None, False))
159
for sensor in interface.get_sensors():
160
image = gdk.pixbuf_new_from_file(os.path.join(images_dir, "sensors-applet-" + sensor.get_type() + ".png"))
161
self.sensors_store.append(parent, (if_name, sensor.get_name(), image, sensor.get_label(), sensor.is_enabled(), True))
163
tree_view = gtk.TreeView(self.sensors_store)
164
tree_view.set_rules_hint(True)
166
tree_view.append_column(gtk.TreeViewColumn("Sensor", gtk.CellRendererText(), text=1))
167
tree_view.append_column(gtk.TreeViewColumn("Icon", gtk.CellRendererPixbuf(), pixbuf=2, visible=5))
168
cell = gtk.CellRendererText()
169
cell.set_property("editable", True)
170
cell.connect("edited", self.edited_sensor_label_cb)
171
tree_view.append_column(gtk.TreeViewColumn("Label", cell, text=3, visible=5))
172
cell = gtk.CellRendererToggle()
173
cell.connect("toggled", self.toggled_sensor_enabled_cb)
174
tree_view.append_column(gtk.TreeViewColumn("Enabled", cell, active=4, visible=5))
176
scrolled_window = gtk.ScrolledWindow()
177
scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
178
scrolled_window.add(tree_view)
179
vbox_sensors.add(scrolled_window)
181
def changed_temperature_unit_cb(self, combobox):
182
self.applet.settings["temperature-unit"] = temperature_units[combobox.get_active()]
185
No forced update is necessary because the dialog will be hidden when the
186
user clicks on the combobox
189
def changed_update_interval_cb(self, button):
190
self.applet.settings["update-interval"] = interval = button.get_value()
192
# Change the interval of the update callback
193
self.update_callback.change_interval(interval)
195
def edited_sensor_label_cb(self, renderer, path, label):
196
row = self.sensors_store[self.sensors_store.get_iter_from_string(path)]
198
assert row[0] is not None
202
self.active_interface[row[0]].get_sensor(row[1]).set_label(row[3])
204
def toggled_sensor_enabled_cb(self, renderer, path):
205
row = self.sensors_store[self.sensors_store.get_iter_from_string(path)]
207
assert row[0] is not None
211
self.active_interface[row[0]].get_sensor(row[1]).set_enabled(row[4])
213
def setup_main_dialog(self):
214
self.dialog = self.applet.dialog.new("sensors-dialog")
216
self.sensors_vbox = None
217
self.update_callback = self.applet.timing.register(self.update_sensor_values, self.applet.settings["update-interval"], False)
218
self.update_sensor_values()
220
self.dialog_focus_lost_time = time.time()
221
self.applet.connect("button-press-event", self.button_press_event_cb)
222
self.dialog.connect("focus-out-event", self.dialog_focus_out_cb)
224
def button_press_event_cb(self, widget, event):
225
if event.button == 1 and (time.time() - self.dialog_focus_lost_time) > 0.01:
226
if not self.dialog.is_active():
227
self.update_callback.start()
228
self.update_sensor_values()
230
self.update_callback.stop()
232
self.applet.dialog.toggle("sensors-dialog")
234
def dialog_focus_out_cb(self, dialog, event):
235
self.dialog_focus_lost_time = time.time()
236
self.update_callback.stop()
238
def update_sensor_values(self):
239
if self.sensors_vbox is not None:
240
self.sensors_vbox.destroy()
241
self.sensors_vbox = gtk.VBox(spacing=6)
242
self.dialog.add(self.sensors_vbox)
244
# TODO add a message (label) if no sensors have been added
246
for interface in self.active_interface.itervalues():
247
# Only draw sensors that are enabled
248
sensors = [sensor for sensor in interface.get_sensors() if sensor.is_enabled()]
250
# TODO this code smells
251
if len(sensors) == 0:
254
vbox = AWNLib.create_frame(self.sensors_vbox, interface.name())
257
table = gtk.Table(columns=2)
258
table.set_col_spacings(6)
261
for sensor in sensors:
265
image = gdk.pixbuf_new_from_file(os.path.join(images_dir, "sensors-applet-" + sensor.get_type() + ".png"))
266
if sensor.get_sensor_type() is Sensor.UNIT_TEMPERATURE:
267
overlay_image = gdk.pixbuf_new_from_file(os.path.join(images_dir, self.get_overlay_image_name(sensor) + "-temp-icon.png"))
268
overlay_image.composite(image, 0, 0, 22, 22, 0, 0, 1.0, 1.0, gdk.INTERP_NEAREST, 255)
269
image = gtk.image_new_from_pixbuf(image)
270
image.props.xalign = 0.0
272
label = gtk.Label(sensor.get_label())
273
label.props.xalign = 0.0
274
if sensor.get_sensor_type() is Sensor.UNIT_TEMPERATURE:
275
temp_unit = self.applet.settings["temperature-unit"]
276
value = int(self.convert_temp_unit(sensor.get_value(), sensor.get_unit(), temp_unit))
278
if temp_unit != "Kelvin":
279
unit_label = str(value) + " \xc2\xb0" + temp_unit[0]
281
unit_label = str(value) + " " + temp_unit[0]
283
unit_label = str(sensor.get_value()) + " " + sensor.get_unit()
284
unit_label = gtk.Label(unit_label)
285
unit_label.props.xalign = 1.0
287
table.attach(image, 0, 1, i - 1, i, xoptions=gtk.FILL)
288
table.attach(label, 1, 2, i - 1, i, xoptions=gtk.FILL)
289
table.attach(unit_label, 2, 3, i - 1, i, xoptions=gtk.FILL)
291
if self.update_callback.is_started():
292
self.dialog.show_all()
294
def get_overlay_image_name(self, sensor):
295
temperature = sensor.get_value()
297
vh = sensor.get_very_high_temperature()
298
vl = sensor.get_very_low_temperature()
301
h = int(vh - (high_to_very_high_range / 100) * diff)
302
l = int(vl + (very_low_to_low_range / 100) * diff)
304
temperatures = {"very-high": (1000, vh), "high": (vh - 1, h), "normal": (h - 1, l), "low": (l - 1, vl), "very-low": (vl - 1, -1000)}
305
return [key for key, value in temperatures.iteritems() if temperature <= value[0] and temperature >= value[1]][0]
307
def convert_temp_unit(self, value, old_unit, new_unit):
308
if old_unit == new_unit:
311
if old_unit == "Celcius":
312
if new_unit == "Kelvin":
314
elif new_unit == "Fahrenheit":
315
return value * 9.0 / 5.0 + 32.0
316
elif old_unit == "Kelvin":
317
if new_unit == "Celcius":
319
elif new_unit == "Fahrenheit":
320
return (value - 273.0) * 9.0 / 5.0 + 32.0
321
elif old_unit == "Fahrenheit":
322
if new_unit == "Celcius":
323
return 5.0 * (value - 32.0) / 9.0
324
elif new_unit == "Kelvin":
325
return 5.0 * (value - 32.0) / 9.0 + 273.0
328
if __name__ == "__main__":
329
applet = AWNLib.initiate({"name": applet_name, "short": "sensors",
330
"version": applet_version,
331
"description": applet_description,
334
"copyright-year": 2008,
335
"authors": ["onox <denkpadje@gmail.com>"],
336
"settings-per-instance": True})
337
SensorsApplet(applet)
b'\\ No newline at end of file'