Simple Application Indicator.

Posted on | пятница, 1 июля 2011 г. | No Comments

Все описанное ниже касается Ubuntu 11.04 и gnome 2.32

Предисловие

Подробно о том, что из себя представляет панель и область уведомлений описано на ubuntu wiki: https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators

Хорошие примеры здесь и здесь

Большую часть информации "зачерпнул" из указанных выше источников.



Основное

модуль appindicator

Первым делом импортируем модуль appindicator (appindicator API)

import appindicator


и конечно без gtk не обойтись

import pygtk
pygtk.require('2.0')
import gtk

создание индикатора

Меню будет создаваться при инициализации класса SimpleAppIndicatorMenu.

self.ind = appindicator.Indicator ("example-simple-client", \
                                   "indicator-messages", \ 
                      appindicator.CATEGORY_APPLICATION_STATUS)

Первый аргумент: уникальный идентификатор приложения
второй: иконка
третий: категория, влияет на расположение иконки.

категории:
CATEGORY_APPLICATION_STATUS
CATEGORY_COMMUNICATIONS
CATEGORY_SYSTEM_SERVICES
CATEGORY_HARDWARE
CATEGORY_OTHER

Статус индикатора:
self.ind.set_status(appindicator.STATUS_ACTIVE)
вариантов статуса всего три:
STATUS_PASSIVE : иконка не отображается
STATUS_ACTIVE : иконка видима
STATUS_ATTENTION : иконка меняется на "угрожающую", привлекая тем самым внимание пользователя. Например, дает знать что пришло новое сообщение.

меню

Плавно переходим к меню:

self.menu = gtk.Menu()

Пункты меню могут быть 3-х видов: labels, checkboxes, radio buttons и images

Labels - обычный текст


item = gtk.MenuItem("Regular Menu Item")
self.menu.append(item)

неактивный элемент меню

Пункт меню можно сделать неактивным, это позволяет приложениям отображать полезную информацию в меню, например, dropbox отображает размер свободного места.

disable_item = gtk.MenuItem("Disable Menu Item")
disable_item.set_sensitive(False)
self.menu.append(disable_item)

"меню с птичкой"


check = gtk.CheckMenuItem("Check Menu Item")
check.set_active(True)
self.menu.append(check)

навигация с клавиатуры

Для навигации с помощью клавиатуры используется символ "_" перед буквой и метод set_use_underline для активации этой возможности. После нажатия буква выделится.
Предыдущий пункт меню принимает форму:

check = gtk.CheckMenuItem("Check _Menu Item")
check.set_use_underline(True)
check.set_active(True)
self.menu.append(check)

RadioMenuItem


radio1 = gtk.RadioMenuItem(None, "Radio1 Menu Item")
radio_group = radio1
self.menu.append(radio1)
Элементы RadioMenuItem должны группироваться. При создании указывается группа к которой принадлежит элемент (первый аргумент), если группа None, то автоматически создается новая группа.
Странно то, что в качестве группы выступает сам элемент меню. Как есть, так есть:

radio1 = gtk.RadioMenuItem(None, "Radio1 Menu Item")
radio_group = radio1
self.menu.append(radio1)

radio2 = gtk.RadioMenuItem(radio_group, "Radio2 Menu Item")
self.menu.append(radio2)

В результате получили два элемента меню принадлежащих одной группе.

без иконок никак

ImageMenuItem - элемент меню с иконкой. В меню будет два таких элемента: первый берет загружает иконку из STOCK-а, второй из файла.


image = gtk.ImageMenuItem("image menu item")
img = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU)
image.set_image(img)
image.set_always_show_image(True)
self.menu.append(image)

image2 = gtk.ImageMenuItem(gtk.STOCK_QUIT)
img = gtk.Image()
img.set_from_file(r"/home/wistful/desktop-notification-bell.png")
image2.set_image(img)
image2.set_always_show_image(True)
image2.connect("activate", self.quit)

После активации последнего меню происходит выход из приложения.

image2.connect("activate", self.quit)
Метод self.quit:

def quit(self, widget, data=None):
        gtk.main_quit()

воссоединение

Указываем, что необходимо отображать все элементы меню и добавляем меню к индикатору

self.menu.show_all()
self.ind.set_menu(self.menu)

запуск


def main():
    gtk.main()
    return 0

if __name__ == "__main__":
    indicator = SimpleAppIndicatorMenu()
    main()

Эпилог

Полностью модуль здесь

D-BUS однако

Posted on | суббота, 18 июня 2011 г. | No Comments

Теория

D-BUS можно представить как центральный канал, через который приложения и сервисы могут обмениваться данными. Более того, с помощью D-BUS одно приложение может управлять другим, а это уже очень интересно.

D-BUS состоит из двух типов шин(bus): системной (System bus) и пользовательской (Session bus). Системная шина одна на всех, а пользовательская соответственно разная для каждого пользователя.

Список объектов подключенных к шине удобно просматривать командой qdbusviewer.
Каждому объекту присваивается уникальный идентификатор вида :x.xx. Дополнительно, объект может иметь и собственное уникальное имя, например, org.freedesktop.Notifications. Создавать или нет символьное представление каждое приложение решает самостоятельно. У каждого объекта также есть свой путь, например, /org/freedesktop/Notifications.
Для доступа к объекту необходимо знать идентификатор объекта(присваиваемый или собственный) и путь к этому объекту.
Доступ к объекту подразумевает под собой доступ к некоторому набору его методов и сигналов, который называется интерфейсом (Interface).
Взаимодействие происходит с помощью сообщений. Сообщения могут быть 4-х типов: вызовы методов, сигналы, результаты методов, ошибки.

Больше об архитектуре D-BUS можно почитать по ссылкам:
http://www.linux.org.ru/wiki/en/D-Bus
http://wiki.linuxformat.ru/index.php/LXF99:D-Bus
http://www.freedesktop.org/wiki/IntroductionToDBus

От теории к практике.

Первое, что приходит в голову это вывод сообщений на экран. Поможет в этом деле объект org.freedesktop.Notifications расположенный где-то здесь: /org/freedesktop/Notifications. К сожалению, qdbusviewer лишь показывает, что у объекта есть метод Notify, но не позволяет узнать его аргументы. Получить эту информацию позволит команда gdbus. (не путать с qdbus !!!!) Подробно о команде можно узнать здесь.

Начнем:
gdbus introspect --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications

Notify(in s app_name,
in u id,
in s icon,
in s summary,
in s body,
in as actions,
in a{sv} hints,
in i timeout,
out u return_id);

Параметры:
app_name - имя приложения
id - идентификатор сообщения которое нужно заменить. Это на случай, если сообщение уже отображается, а вам хочется изменить его текст.
icon - идентификатор иконки (например, gtk-dialog-info) или путь к файлу с иконкой
summary - однострочный заголовок сообщения
body - сообщение, поддерживается разметка (http://www.galago-project.org/specs/notification/0.9/x161.html)
actions: оставляем пустым - []
hints: оставляем пустым {}
timeout: время отображения сообщения в мск.

Возвращаемое значение return_id - идентификатор сообщения. Именно его можно использовать в качестве второго аргумента.

команда: gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify "test_application" 0 gtk-dialog-info "Notification title" "Notification body message" [] {} 25000
отображает сообщение с иконкой.

Заметки на полях

я уже упоминал команду qdbus, она также позволяет взаимодействовать с объектами соединенными с D-BUS. Но мне так и не удалось вывести сообщение с ее помощью, несмотря на то, что остальные методы объекта org.freedesktop.Notifications вызывались без проблем. Например: qdbus org.freedesktop.Notifications /org/freedesktop/Notifications GetCapabilities выводит список поддерживаемых фич, а qdbus org.freedesktop.Notifications /org/freedesktop/Notifications GetServerInformation - product name of the server, vendor name, server's version number

Итоги

D-BUS очень удобен, особенно учитывая, что большое количество приложений поддерживают эту возможность. Например можно отправить систему в спящий режим, отключить монитор, управлять аудио и видео плеерами, ....

P.S.

Использовалась Ubuntu 11.04, Gnome 2.32

Bye Unity, Hello Gnome

Posted on | вторник, 14 июня 2011 г. | No Comments

Терпение закончилось

В течении 3 недель уверял себя, что Unity это будущее Ubuntu и что надо всего лишь привыкнуть.
Не смог. Непонятно зачем пиндосы из Canonical оставили по умолчанию эту сырую поделку.

По порядку

К панели слева привык очень быстро. Даже хотел добавить иконки для запуска некоторых скриптов. Вот только это сделать нельзя. НЕЛЬЗЯ!!!
На самом деле можно, но через одно место, точнее через два.
Первый: надо руками создать файлик со специальным именем и специальными параметрами и положить его в специальное место.
Второй: погуглить питоновскую программку, которая сделает тоже самое, но с комфортом.
Вот так в линуксе с человеческим лицом добавляется иконка на панель.

Еще луч гнева

Все приложения "прилипают" к верхнему левому углу. ЗАЧЕМ ???
Это не все, они еще открываются в развернутом виде. Какая-то падла решила, что это очень круто. Влево и на весь экран. Смотрится просто впечатляюще на широкоформатных мониторах.

Меню приложения отдельно от приложения

Ни больше ни меньше, отдельно и все тут. Если окно занимает, внезапно, четверть экрана или меньше, то придется тянуться мышкой в самый вверх. Pidgin и ему подобные приложения становятся "мега удобными".

Последняя капля

Разработчики Unity наверняка не пользуются заметками. Заметки показывают всю ущербность Unity. Одинокое маленькое окно постоянно появляющееся в левом верхнем углу, без панели меню (меню то нынче отдельно от приложения), и ... это окно нельзя переместить т.к. мышой тупо незачто зацепиться.

Итог

Как по мне, Unity сейчас целесообразно использовать на нетбуках или ноутбуках с маленьким экраном. Возможно даже на телефончиках будет неплохо смотреться, но для больших широкоформатных мониторов еще надо допиливать.

P.S.

Конечно, это линукс и настроить Unity под свои нужды можно. Но это начинает бесить: вместо комфортной работы в удобной оболочке тратишь время на ее настройку.
Возможно в следующий раз ...