Pull to refresh

DataEngine и Python2 или Как я писал свой виджет

Reading time 4 min
Views 4.1K

Вместо предисловия


Посидев немного в awesome, я решил вернуться на более привычные, обвешанные множеством нужных и не очень плюшек, кеды (KDE4). Через некоторое время, я решил убрать страшненький самописный виджет карамбы (SuperKaramba) и заменить его более элегантным и простым виджетом плазмы. Требования к нему были простые: это должен быть простенький виджет на панели, который бы отображал в виде текста всю основную (вернее, востребованную мной) информацию. Порыскав по kde-look.org, я нашел один виджет, который устраивал меня в достаточной мере. Однако, мне нужны были некоторые дополнительные функции, которые не были реализованы в этом виджете. Также, автор не предусмотрел возможность легкой конфигурации виджета, и для его настройки приходилось лезть в исходный скрипт, написанный на JavaScript.
Через несколько итераций настройки уже имеющегося виджета, ввиду отсутствия у меня каких либо представлений о JS, я решил написать свой виджет. Из языков программирования был выбран Python2, в котором я более-менее смыслю. Сказано — сделано. За вечер я написал первую версию виджета, вполне работоспособную. Позже, при тестировании обнаружилось, что он имеет неприятную особенность подвисать во время обновления. Во-первых, это было связано с тем, что все поля обновлялись одновременно. А во-вторых, и это, пожалуй, самое главное — для парсинга файлов с данными (среди них /proc/stat и файл, в котором содержится информация о переданном/полученном трафике) нужна некоторая задержка. Если выставить на них по 0.2 секунды, то в итоге виджет подвисает почти на 0.5 секунд, что заметно даже невооруженным глазом.
Тогда мной была предпринята попытка переписать код, включив DataEngine, который я подсмотрел в исходном виджете. Ниже пойдет речь об использовании этого модуля в Python2.

Единственная проблема использования этого модуля — это отсутствие какой-либо документации по нему в Python2. Есть для cpp с описанием требуемых параметров в функции (в Python нет и этого), и есть небольшая заметка в девелоперском туториале с совсем уж детским примером. Из-за этого работать пришлось вслепую по образу и подобию, поэтому что-то наверняка можно сделать изящнее и проще. Сразу, перед тем, как перейду к описательной части, замечу, что мои навыки в программировании не такие уж и больше, что тоже не может не сказаться на качестве кода. Так что, прошу меня извинить, если вдруг я что-то делаю неправильно.
Также, в цели данной статьи не входит гайд по написанию плазмоидов на Python, для этого уже существуют другие статьи, например: раз и два.
Итак, после длинного введения, приступим.

Основы


Посмотреть список доступных сервисов можно воспользовавшись утилитой plasmaengineexplorer (в ArchLinux входит в пакет plasmate, доступный в ауре). Интерфейс прост, как валенок:

Выбрали нужный нам инструмент (engine) из выпадающего списка, появилось много строк, которые и содержат информацию (в Python передается в виде словаря). Следует заметить, что, по крайней мере, в случае инструмента systemmonitor, переменная также имеет ключ 'value', который и содержит интересующую информацию.
Подключается инструмент еще проще (в классе самого виджета):
from PyKDE4.plasma import Plasma

def connectToEngine(self):
    """function to initializate engine"""
    self.systemmonitor = self.dataEngine("systemmonitor")

Единственная опция — это наш DataEngine. Однако, мы еще не подключились к нужным данным, потому ничего и не увидим. Если мы хотим узнать среднее значение загрузки процессора, то продолжение функции будет выглядеть так:
    self.systemmonitor.connectSource("cpu/system/TotalLoad", self, 1000)

Здесь три параметра. Первый — то, куда мы обращаемся — source (вообще, требует формат QString, хотя, обычно, можно подсунуть и простую строку). Это есть первая колонка в plasmaengineexplorer. Второй параметр — визуализация (куда параметр будет отправлен), указываем сам виджет. Третий параметр — интервал обновления (int), мс — время, через которое мы будем запрашивать, обновилась ли информация. В общем-то, уже все готово, осталось только дописать функцию обновления:
@pyqtSignature("dataUpdated(const QString &, const Plasma::DataEngine::Data &)")
def dataUpdated(self, sourceName, data):
    """function to refresh data"""
    if (sourceName == "cpu/system/TotalLoad"):
        value = str(round(float(data[QString(u'value')]), 1))
        cpuText = "%5s" % (value)

cpuText — строка из пяти символов — например, '100.0'. Немного комментариев — data (здесь) наш словарик, sourceName — source, который обновляется (указывали выше), data[QString(u'value')] — интересующее нас значение (за другими ключами — опять же, к plasmaengineexplorer). Вуаля, виджет готов, осталось только вывести полученное значение и все. Замечу, что обновить текст виджета имеет смысл прямо в этой функции.

Немного частностей


Обновление

Если Вы используете только DataEngine, создавать таймер не нужно, данные будут обновляться сами. Также, стоит заметить, что у меня не получилось подружиться с инструментом powermanager (для чтения заряда батареи) — это было связано с тем, что значение заряда не обновлялось само по себе (если подключен адаптор питания). Соответственно, не происходило чтение начального значения, до тех пор пока оно не изменится (если, конечно, я правильно понимаю).

Одновременное обновление

Может понадобиться, если Вы хотите, например, посчитать загрузку памяти в %. Честно признаюсь, что у меня не получилось этого сделать. Однако, если я не ошибаюсь, копать нужно в сторону такой комбинации:
self.engine.addSource(self.container)
self.engine.connectAllSources(self, 1000)

Добавляем source'ы, а затем их разом подключаем. Проблема с определением контейнера (тип переменной PyKDE4.plasma.Plasma.DataContainer). Можно создать свой контейнер и набить его данными, но связать его с уже имеющимся source'ом я не смог. Поэтому, в текущей версии виджета значения, которые дальше используются, записываются в переменные, которые обрабатывает специальная функция после окончания таймера.

Достоинства и недостатки

Параллельное обновление элементов виджета, отсутствие задержек (данные читаются тут же) и большая скорость работы. Также, стоит заметить, что DataEngine содержит много всяких полезностей, которые могут быть использованы при написании виджетов. Из недостатков — зависимость от наличия модуля в системе (пакет kdebindings-python2 в случае ArchLinux).

Послесловие


Исходники виджета доступны на github или на kde-look.org. В итоговом варианте виджет (если вдруг кому интересно) выглядит так (хотя, предусмотрена достаточно гибкая настройка):

Приношу свои извинения, если на Ваш взгляд текст сильно размазан, при желании, его можно ужать раза в два.
Tags:
Hubs:
+4
Comments 2
Comments Comments 2

Articles