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