Pull to refresh

Python. Плазма-змей

Reading time 4 min
Views 3.1K

KDE4


Все уже успели пройтись по сырости технологии, внешнему виду, концепциям интерфейса, но настоящие апологеты знают — когда KDE4 войдёт в стабильную фазу, все станет хорошо, и слабые духом отступники, которые видите ли не могли потерпеть годик постоянных глюков, вернутся.

Теперь серьезно — ключевая технология нового KDE — Plasma. Таким образом, чтобы в KDE было жить хорошо, надо создавать плазмоиды. Спасибо C и C++ за работу ядра, X сервера и KDE, а мы, поколение web-разработчиков, да и вообще людей привыкших к простоте, вполне можем обжить систему используя более знакомые нам языки, к примеру Python, который, как известно, поставляется с батарейками.



Пакет


Для работы всего описанного требуется поддержка python плазмоидов вашей версией KDE. В Последнем релизе Ubuntu такая поддержка есть.

Python плазмоиды организовываются в виде пакетов. Пакет это файловая структура завернутая в zip:
./contents
./contents/code
./contents/code/main.py
./metadata.desktop


Итак, начнем. Создайте папку plasma-informer, а в ней папки и файлы из листинга. Первым на очереди metadata.desktop, будем считать, что поля достаточно говорящие:
[Desktop Entry]
Encoding=UTF-8
Name=Informer about something
Type=Service
ServiceTypes=Plasma/Applet
X-Plasma-API=python
X-Plasma-MainScript=code/main.py
Icon=chronometer

X-KDE-PluginInfo-Author=Хабрагражданин
X-KDE-PluginInfo-Email=deeppy@kuku.ya
X-KDE-PluginInfo-Name=plasma-informer
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://habrahabr.ru
X-KDE-PluginInfo-Category=Tests
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true


Описание пакета конечно же важная часть для хорошей интеграции пакета во всяческие списки, но соль земли лежит в contents/code/main.py, который снабжен массой комментариев:
#! /usr/bin/python                                                                            
# -*- coding: utf8 -*-                                                                        

from PyQt4.QtCore import *
from PyQt4.QtGui import * 
from PyKDE4.kdecore import *
from PyKDE4.kdeui import *  
from PyKDE4.plasma import Plasma
import plasma                   

class MyLabel(Plasma.Label):
    "Надпись с автоматической подгонкой по размеру, горизонтальной подгонкой."
    def setText(self,text):                                                   
        "Переопределим процедуру. Будем в зависимости от текста устанавливать размеры нашей надписи."
        width = QFontMetrics(self.font()).width(text)                                                
        self.setMinimumWidth(width)                                                                  
        self.setMaximumWidth(width)                                                                  
        Plasma.Label.setText(self,text)                                                              

class PyInfApplet(plasma.Applet):
    "Главный апплет. Действие - выводит нечто, подозревается в связях с НЛО..."
    def __init__(self,parent,args=None):
        "А это собственно инициализация, обычное дело для создания экземпляра класса."
        plasma.Applet.__init__(self,parent)
        # А это мы просто вызвали инициализацию предка, предки они всё лучше знают!

    def init(self):
        # Конфигурировать пока собственно нечего
        self.setHasConfigurationInterface(False)
        # Без этой штуки работает глюкаво, попробуйте убрать и посмотрите на результат
        self.setAspectRatioMode(Plasma.IgnoreAspectRatio)

        # Стартуем таймер, для всяческих там обновлений содержимого, пока на будущее
        self.timer = self.startTimer(1000)

        # Создаем "раскладку", элемент, на котором раскладываются остальные виджеты
        self.mlayout = QGraphicsLinearLayout(Qt.Horizontal)
        # Создадим надпись
        self.label = MyLabel()
        self.label.setText('Yahooho')
        # И расположим на нашей раскладке
        self.mlayout.addItem(self.label)

        # Так вот, уважаемая Plasma, эта раскладка и есть лицо нашего апплета!
        self.setLayout(self.mlayout)

    def timerEvent(self,ev):
        "Когда нибудь здесь будет что то происходить"
        pass

    def constraintsEvent(self, constraints):
        if constraints & Plasma.SizeConstraint:
            self.resize(self.size())

def CreateApplet(parent):
    "Функция которая вернёт экземпляр нашего апплета Plasma"
    return PyInfApplet(parent)



Как видно из кода, апплет ничего не делает, а просто занимает панель глупой надписью. Но для экспериментов с плазмоидом его пора бы установить и посмотреть как он работает. В корне пакета выполните zip -r ../plasma-informer.zip *, а затем установите его: plasmapkg -i ../plasma-informer.zip

Пакет будет установлен в домашнем каталоге в папку .kde/share/apps/plasma/plasmoids/plasma-informer, и продолжать работы по развитию можно редактируя файл .kde/share/apps/plasma/plasmoids/plasma-informer/contents/code/main.py. Второе — на результат надо смотреть, а все питонисты знают свойство пакетов — если вы уже импортировали пакет, то чтобы его код обновить, желательно перегрузить весь python-код. В нашем случае это равняется перегрузке Plasma, что вообще рискованная операция — останетесь с голым рабочим столом без элементов управления. Итак, для джедаев есть специальная утилита — plasmoidviewer.

~$ plasmoidviewer plasma-informer



Так как плазмоид уже установлен, вы можете посмотреть на него: plasmoidviewer plasma-informer

Для нагрузки нашего информера смыслом отредактируйте код timerEvent:
    def timerEvent(self,ev):
        "Когда нибудь здесь будет что то происходить"
        self.label.setText(open('/proc/loadavg','r').read().strip())


Вот теперь информер и вправду о чем то таком нас информирует.



А вот с размещением второго апплета (еще один вы можете видеть на картинке, он служит для управления Amarok-ом) возникли проблемы при импорте. Маленький обходной маневр это отредактировать /usr/share/kde4/apps/plasma_scriptengine_python/plasma_importer.py — в классе PlasmaImporter я вынес из __init__ объявление self.toplevel={} и сделал таким образом:
class PlasmaImporter(object):
    toplevel = {}
    def __init__(self):
        sys.path.append('<plasma>')
        sys.path_hooks.append(self.hook)



Такая фишка делает toplevel принадлежащим классу а не экземпляру объекта, как то раз в самом начале меня это поставило в ступор часа на два, а здесь помогло.

Домашнее задание — мониторинг собственной кармы, код для проверки принимается в комментарии.

P.S. cat plasma-restart
kbuildsycoca4
kquitapp plasma
plasma


P.P.S. Поставил KDE4.2, вылез баг, точнее немного сменились модули. Замените строчку import plasma на from PyKDE4 import plasmascript as plasma, и все снова заработает.
P.P.P.S. После чреды обновлений, не помню уже с какого момента, опять поломалось. Ну и решение — в metadata.desktop добавить строчку: X-Plasma-MainScript=code/main.py
Tags:
Hubs:
+42
Comments 22
Comments Comments 22

Articles