class QCPUMonitor(QMonitor): percent = qmlProperty(float) count = qmlProperty(int) cpus = qmlProperty(QVariant) def __init__(self): QMonitor.__init__(self, CPUMonitor(), "CPU", "cpu.qml") self.qtypes_ += [QCPU] self.monitorheight_ = 0 self.percent_ = 0 self.count_ = 0 print(self.monitor.config) @pyqtSlot() def update(self): QMonitor.update(self) self.percent = self.monitor.percent self.count = self.monitor.count #print(self.percent,self.monitor.cpus) cpus = self.monitor.cpus.copy() cpus.sort(reverse=True) if not self.fieldInitialized('cpus'): self.cpus = [QCPU(percent) for percent in cpus] else: for cpu, percent in zip(self.cpus, cpus): cpu.percent = percent self.monitorHeight = 65
class QDisk(QmlObject): mountpoint = qmlProperty(str) usepercent = qmlProperty(float) def __init__(self, mountpoint, usepercent): QObject.__init__(self) self.mountpoint = mountpoint self.usepercent = usepercent
class QBattery(QmlObject): percent = qmlProperty(float) dead = qmlProperty(float) label = qmlProperty('QString') status = qmlProperty('QString') def __init__(self, label, *args): QObject.__init__(self) self.label = str(label) self.update(*args) def update(self, percent, dead, status): self.percent = percent self.dead = dead self.status = status
class QInterface(QmlObject): name = qmlProperty('QString') txspeed = qmlProperty(float) rxspeed = qmlProperty(float) def __init__(self, name, info): QObject.__init__(self) self.name_ = name self.txspeed_ = info["txspeed"] self.rxspeed_ = info["rxspeed"] def update(self, name, info): self.name = name self.txspeed = info["txspeed"] self.rxspeed = info["rxspeed"]
class QVolumeMonitor(QMonitor): volume = qmlProperty(int) muted = qmlProperty(bool) def __init__(self): QMonitor.__init__(self, VolumeMonitor(), "Volume", "volume.qml") self.muted_ = False self.volume_ = 0 self.volumeChanged.connect(self.onVolumeChanged) self.mutedChanged.connect(self.onMutedChanged) self.monitorHeight_ = 100 def onVolumeChanged(self, volume): print("new volume:", volume) def onMutedChanged(self, muted): print("toggle mute", muted)
class QMemory(QmlObject): label = qmlProperty('QString') used = qmlProperty('quint64') free = qmlProperty('quint64') total = qmlProperty('quint64') percent = qmlProperty(float) def __init__(self, label, memory): QObject.__init__(self) self.label_ = label self.update(memory) def update(self, memory): self.used = memory.used self.free = memory.free self.total = memory.total self.percent = memory.percent
class QNetworkMonitor(QMonitor): interfaces = qmlProperty(QVariant) datapoints = qmlProperty(int) maxspeed = qmlProperty(float) # XXX QQmlListProperty ? rxspeed = qmlProperty(QVariant) txspeed = qmlProperty(QVariant) def __init__(self): QMonitor.__init__(self, NetworkMonitor(), "Network", "network.qml") self.monitorHeight_ = 0 self.datapoints_ = 20 self.maxspeed_ = 0 self.rxspeed_ = [0] * self.datapoints_ self.txspeed_ = [0] * self.datapoints_ self.qtypes_ += [QInterface] @pyqtSlot() def update(self): QMonitor.update(self) rx = 0 tx = 0 if not hasattr(self, 'interfaces_'): self.interfaces_ = [ QInterface(name, info) for name, info in self.monitor.interfaces.items() ] else: for iface, info in self.monitor.interfaces.items(): data = [x for x in self.interfaces_ if x.name == iface] if not data: self.interfaces_.append(QInterface(iface, info)) self.interfacesChanged.emit(self.interfaces_) else: data = data[0] data.update(iface, info) rx += info["rxspeed"] tx += info["txspeed"] self.rxspeed[:] = self.rxspeed[1:] + [rx] self.txspeed[:] = self.txspeed[1:] + [tx] self.maxspeed = max(max(self.rxspeed), max(self.txspeed)) self.monitorHeight = len(self.monitor.interfaces) * 32 + 50
class QMonitor(QmlObject): monitorName = qmlProperty('QString') monitorView = qmlProperty('QString') monitorHeight = qmlProperty(int) updateInterval = qmlProperty(int) def __init__(self, mon, name, view): QObject.__init__(self) self.qtypes_ = [self.__class__] self.monitor = mon self.monitorView_ = "../../plugins/" + name.lower() + "/" + view self.monitorName_ = name self.updateInterval_ = mon.config["refresh"] * 1000 if "height" in mon.config: self.monitorHeight = mon.config.setdefault("height", 100) def loadConfig(self, config): self.monitor.loadConfig(config) #print(self.__class__.__name__, self.monitor.config) self.updateInterval = self.monitor.config["refresh"] * 1000 if "height" in self.monitor.config: self.monitorHeight = self.monitor.config["height"] #def defaultConfig(self): # default = self.monitor.defaultConfig() # default["height"] = 1000 # return default def fieldInitialized(self, name): return hasattr(self, name + '_') def types(self): return self.qtypes_ def update(self): self.monitor._update(time.monotonic())
class QMemoryMonitor(QMonitor): memories = qmlProperty(QVariant) def __init__(self): QMonitor.__init__(self, MemoryMonitor(), "Memory", "memory.qml") self.qtypes_ += [QMemory] ram = QMemory("RAM", self.monitor.memory) swap = QMemory("SWAP", self.monitor.swap) self.hasSwap = self.monitor.monitorswap self.memories = [ram, swap] if self.hasSwap else [ram] self.monitorHeight = 60 if self.hasSwap else 30 @pyqtSlot() def update(self): QMonitor.update(self) self.memories[0].update(self.monitor.memory) if self.hasSwap: self.memories[1].update(self.monitor.swap)
class QStorageMonitor(QMonitor): disks = qmlProperty(QVariant) def __init__(self): QMonitor.__init__(self, StorageMonitor(), "Storage", "storage.qml") self.monitorHeight_ = 0 self.qtypes_ += [QDisk] @pyqtSlot() def update(self): QMonitor.update(self) if not hasattr(self, 'disks_'): self.disks_ = [ QDisk(mountpoint, data["usage"].percent) for mountpoint, data in self.monitor.disks.items() ] for disk in self.disks_: new = self.monitor.disks[disk.mountpoint]["usage"].percent disk.usepercent = new self.monitorHeight_ = 30 * len(self.disks_)
class QBatteryMonitor(QMonitor): batteries = qmlProperty(QVariant) # remaining def __init__(self): QMonitor.__init__(self, BatteryMonitor(), "Battery", "battery.qml") self.qtypes_ += [QBattery] self.monitorHeight_ = 0 @pyqtSlot() def update(self): QMonitor.update(self) batteries = self.monitor.batteries if not self.fieldInitialized('batteries'): self.batteries = [ QBattery(bat.uid, bat.percent, bat.percent_dead, bat.status) for bat in batteries ] else: for battery, bat in zip(self.batteries, batteries): battery.update(bat.percent, bat.percent_dead, bat.status) self.monitorHeight_ = 40 * len(self.batteries)
class QCPU(QmlObject): percent = qmlProperty(float) def __init__(self, percent): QObject.__init__(self) self.percent = percent
class Header(QmlObject): NET_NONE = 0 NET_ETHERNET = 1 NET_WIFI = 2 wifiEssid = qmlProperty('QString') wifiSignal = qmlProperty(int) ethernetSpeed = qmlProperty(int) running = qmlProperty(bool) connectionType = qmlProperty(int) def __init__(self): QObject.__init__(self) self.wifiEssid_ = 0 self.wifiSignal_ = -1 self.running_ = True self.connectionType = Header.NET_WIFI # FIXME self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socketfd = self.socket.fileno() # TODO use configuration for the interfaces by default ethifaces = self.getEthernetIfaces() self.ethiface = ethifaces[0] if ethifaces else None wlifaces = self.getWirelessIfaces() self.wliface = wlifaces[0] if wlifaces else None self.update() def getEssid(self, interface): essid = array.array("B", b"\0" * maxLength["essid"]) essidPointer, essidLength = essid.buffer_info() request = array.array( "B", bytes(interface.ljust(maxLength["interface"], "\0"), 'ascii') + struct.pack("PHH", essidPointer, essidLength, 0)) fcntl.ioctl(self.socketfd, SIOCGIWESSID, request) name = str(essid, 'ascii').rstrip("\0") if name: return name return None def getIfaces(self, prefix): interfaces = [] with open("/proc/net/dev", "r") as f: for line in f.readlines()[2:]: data = line.rstrip().split() ifname = data[0][:-1] if ifname.startswith(prefix): interfaces.append(ifname) return interfaces def getEthernetIfaces(self): return self.getIfaces(("en", "et")) def getLinkInfo(self): iface = bytes(self.ethiface, 'ascii') ecmd = array.array('B', struct.pack('2I', ETHTOOL_GLINK, 0)) ifreq = struct.pack('16sP', iface, ecmd.buffer_info()[0]) fcntl.ioctl(self.socketfd, SIOCETHTOOL, ifreq) res = ecmd.tostring() up = bool(struct.unpack('4xI', res)[0]) if not up: return None, None, None, False ecmd = array.array('B', struct.pack('I39s', ETHTOOL_GSET, b'\x00' * 39)) ifreq = struct.pack('16sP', iface, ecmd.buffer_info()[0]) try: fcntl.ioctl(self.socketfd, SIOCETHTOOL, ifreq) res = ecmd.tostring() speed, duplex, auto = struct.unpack('12xHB3xB24x', res) except IOError: speed, duplex, auto = 65535, 255, 255 if speed == 65535: speed = 0 if duplex == 255: duplex = None else: duplex = bool(duplex) if auto == 255: auto = None else: auto = bool(auto) return speed, duplex, auto, up def getWirelessIfaces(self): return self.getIfaces('wl') def getWirelessInfo(self): lines = None with open('/proc/net/wireless') as f: for line in f.readlines()[2:]: data = line.split() ifname = data[0][:-1] if ifname != self.wliface: continue essid = self.getEssid(ifname) signal = int(float(data[2])) signal = signal * 100 / 70 return signal, essid return None, None def autodetect(self): if self.ethiface: speed, _, _, up = self.getLinkInfo() if up: self.ethernetSpeed = speed return Header.NET_ETHERNET if self.wliface: signal, essid = self.getWirelessInfo() if signal: self.wifiSignal = signal self.wifiEssid = essid return Header.NET_WIFI return Header.NET_NONE @pyqtSlot() def update(self): self.connectionType = self.autodetect()