DataEngine и Python2: Создание нового DataEngine

в 17:04, , рубрики: kde4, plasma, python, виджеты, разработка, метки: , ,

Первую мою небольшую заметку по DataEngine можно найти здесь. Вообще, я не планировал продолжать эту тему. Но в процессе разработки было решено включить набор новых меток, например: загрузка GPU, температура GPU, температура HDD. В процессе реализации я столкнулся с некоторыми трудностями («плазма падает» ©), а в процессе поиска выхода из ситуации было решено создать новый DataEngine с блэкджеком и блудницами.
Для тех, кто что то пропустил. DataEngine — это специальный класс (plasmascript.DataEngine) в модуле PyKDE4. По сути — список словарей, каждый словарик при обращении к нему выдает какую то полезную информацию. Пожалуй, самые ходовые «словари» — systemmonitor и time, назначение обоих очевидно. Меня терзают смутные сомнения, что половина KDE4 так или иначе завязаны на работу этих самых DataEngine. Цель данного топика — создать свой DataEngine с нужными нам словарями.
Кого заинтересовало, прошу под хабракат.

Рассматривать будет все с точки зрения монитора температуры GPU, остальное делается легким движением руки (или пальцев) по образу и подобию. Приступим-с.

Вызовем нужные модули и объявим класс:

from PyQt4.QtCore import *
from PyKDE4.kdecore import *
from PyKDE4 import plasmascript
import commands


class ExtendedSysMon(plasmascript.DataEngine):
    def __init__(self, parent, args=None):
        """dataengine definition"""
        plasmascript.DataEngine.__init__(self, parent)

 
    def init(self):
        """initialization"""
        self.setMinimumPollingInterval(333)
        
        # setup gpu device
        self.gpudev = ''
        commandOut = commands.getoutput("lspci")
        if (commandOut.lower().find('nvidia') > -1):
            self.gpudev = 'nvidia'
        elif (commandOut.lower().find('radeon') > -1):
            self.gpudev = 'ati'

Первые три модуля — для работы инструмента (engine), последний — для получения температуры. В __init__, как и все культурные люди ничего не делаем, кроме объявления. В init все довольно просто. Задаем минимальный интервал запросов (333) в мс, и определяем, какой девайс у нас стоит (nvidia или ati). Конечно, второе можно сделать лучше.
Создадим «сурсы» («словари»):

    def sources(self):
        """create sources"""
        sources = ["gputemp"]
        return sources
    
    
    def sourceRequestEvent(self, name):
        return self.updateSourceEvent(name)

Запомнили (записали) наши source, нам по ним еще обращаться. Функция sourceRequestEvent обрабатывает наши (или не наши) запросы к словарям. Напишем теперь функцию, которая бы это все обрабатывала (updateSourceEvent):

    def updateSourceEvent(self, source):
        """update sources and setup values"""
        if (source == "gputemp"):
            if (self.gpudev == 'nvidia'):
                commandOut = commands.getoutput("nvidia-smi -q -d TEMPERATURE | grep Gpu | tail -n1")
                try:
                    value = "%4s" % (str(round(float(commandOut.split()[2]), 1)))
                except:
                    value = " NA"
            elif (self.gpudev == 'ati'):
                commandOut = commands.getoutput("aticonfig --od-gettemperature | grep Temperature | tail -n1")
                try:
                    value = "%4s" % (str(round(float(commandOut.split()[4]), 1)))
                except:
                    value = " NA"
            else:
                value = " NA"
            self.setData(source, "GPUTemp", QString(value))
 
        return True

Все просто и интуитивно понятно. Получаем строку, парсим ее, вытаскиваем циферку и передаем в словарик. Немного про функцию self.setData(). Имеет три параметра: source (имя словаря, к которому обращаемся, QString), ключ словаря (QString) и значение, соответствующее данному ключу (можно int, можно float или еще что нибудь, тут QString). Замечу, что как и в других нормальных словарях, ключей может быть несколько — так можно создать один source под температуру HDD, в котором 3 ключа — на 3 жестких диска. Ах да, try...except — это для того, чтобы не устраивать унылые проверки наличия ПО/видеокарты и проч. Если source'ов будет много — делаем конструкцию if...elif....
Ну все, скрипт почти готов:

def CreateDataEngine(parent):
    return ExtendedSysMon(parent)

Теперь оформим это все красиво:

$ ls -R extsysmon
extsysmon:
contents  metadata.desktop

extsysmon/contents:
code

extsysmon/contents/code:
main.py

Меня терзают смутные сомнения (исходники листал), что если Вы положите main.py в любую другую директорию, то ничего не запустится, хотя как будто бы все рабочее. И создадим metadata.desktop:

[Desktop Entry]
Encoding=UTF-8
Name=Extended SystemMonitor DataEngine
Comment=Adds gpu, gputemp and hddtemp to DataEngine
ServiceTypes=Plasma/DataEngine
Type=Service
Icon=utilities-system-monitor

X-Plasma-API=python
X-Plasma-MainScript=code/main.py

X-KDE-PluginInfo-Author=%username%
X-KDE-PluginInfo-Email=%e-mail%
X-KDE-PluginInfo-Name=ext-sysmon
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://kde-look.org/
X-KDE-PluginInfo-Category=System Information
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true

Принципиально важно тут — ServiceTypes, X-Plasma-API, X-Plasma-MainScript. Первый — указывает тип (DataEngine), второй — шелл, третий — путь к исходному скрипту (исключая contents). Остальное понятно, как и везде.

Архивируем (из рабочей директории):
zip -qr extsysmon.zip contents metadata.desktop
Устанавливаем:
plasmapkg -t dataengine -i extsysmon.zip
Говорят, указать тип (-t dataengine) здесь обязательно, иначе виджетом определит.

PROFIT!
Красивая картинка, все работает:
DataEngine и Python2: Создание нового DataEngine
Загрузка GPU у меня не определяется, а температуры GPU нет, т.к. дискретная видеокарта выключена.
Исходный код доступен на github. Подключение инструмента и работа с ним — в первой заметке.

Автор: arcan1s

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js