25 января 2009 в 14:12

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

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
+42
921
32

Комментарии (22)

НЛО прилетело и опубликовало эту надпись здесь
0
Deepwalker, #
Все о KDE в kubuntu можно найти здесь — www.kubuntu.org/

С другой стороны не вижу смысла использовать долгоиграющий вариант для десктопа — к чему тут сверх надежность и стабильность? А вот плюшки последние теряете: )

Кстати я гоню, или Kubuntu 8.04 не long-support?
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
0
Gnuava, #
Сверхнадежность и стабильность в дебиане, здесь это просто чуть подправленный experimental. Не зря же в lenny до сих пор 3.5.10. Убунта 8.04 — LTS
0
xiaose, #
Зря. lenny 3.5.1 потому что там другая нумерация. Ubuntu 8.04 значит 2008-й (8) год, апрель (4) месяц — дата выхода релиза. Сейчас последняя версия 8.10 Вам домашнее задание: узнать дату релиза. Подсказку дать?
0
Gnuava, #
Нда. Вы совсем не поняли о чем я.
3.5.10 — версия KDE, считается очень стабильной на данный момент
У Lenny официальный № версии 5.0
Я имел ввиду, что из-за требований к сверхнадежности и сверхстабильности дистрибутива люди просто не будут пихать в уже готовый продукт недоработанные компоненты, коими являлись KDE 4.1
0
xiaose, #
Понял. Извиняюсь.
0
chuwy, #
+4
hellraiser09, #
отлично, но вот бы пара скринов не помешала
+1
Deepwalker, #
Добавил один
0
svartalf, #
В KDE4.1 как минимум, старые версии библиотек (нужны SIP >= 4.7.8 и PyQT >= 4.4.4), поэтому для создания Python плазмоидов необходимо обновиться.
0
Deepwalker, #
Я на днях планирую обновится обновится до 4.2, смотрел в svn и читал в api — есть новые виджеты, которые мне интересны.
+1
ivlis, #
Вот и повод обновится до 4.1, а то я на 4.0 всё сижу :)
+1
geshido, #
завтра уже 4.2 выходит, так что не отставайте :)
0
ivlis, #
Ух ты, хороший повод обновится. Просто компьютер «боевой», боюсь сломать что-нибудь.
+1
Scraelos, #
Кедами не сломаете. В крайнем случае — сломаете кеды ;-) но это ведь не критично =)
А уж 4.0 кеды на боевом компе — это действительно страшно. 4.1 значительно стабильнее, на мой взгяд.
0
ivlis, #
Кстати, особых неприяных багов не наблюдаю, единственное что annoying, это невозможность перенести панель с приложениями наверх — падает плазма.
+1
vrmzar, #
Плазма не падает!
0
KitsonKit, #
Появится KDE 4.2 в Debian — потестим. Спасибо!
0
Deepwalker, #
Потестировал KDE 4.2 в связи с чем маленькое обновление в районе P.P.S.
0
Deepwalker, #
Еще маленькое обновление по последним релизам.

Только зарегистрированные пользователи могут оставлять комментарии.
Войдите, пожалуйста.