# 3. Написання нових додатків

Розширення можливостей Accerciser бажаними для вас функціями
Eitan Isaacson
eitan@ascender.com
Peter Parente
pparent@us.ibm.com
Aline Bessa
alibezz@gmail.com

Creative Commons Share Alike 3.0

Wanderlust
wanderlust@ukr.net 2009

# Написання додатків до Accerciser

Розширення можливостей Accerciser за допомогою додатків стало простішим з часу написання цих настанов. Зважаючи на те, що у настановах було надано дуже докладне пояснення щодо цього питання, цей розділ складається, в основному, з початкового тексту настанов із простими редагуваннями і оновленнями.

В Accerciser передбачено підтримку трьох базових типів додатків:

Базові додатки — ці додатки є похідними від базового класу Plugin. У них не передбачено видимого інтерфейсу, але вони можуть розширювати функціональні можливості Accerciser.

Консольні додатки — ці додатки виводять прості дані до текстової області на вкладці додатка. Не плутайте ці доддати із додатком консолі IPython з пакунка з програмою.

Додатки поля перегляду — основна частина типових додатків Accerciser. Ці додатки мають нетиповий графічний інтерфейс, який буде показано у вкладці.

# Створення базового додатка

Ми створимо спрощену версію додатка швидкого вибору. Цей додаток вибере останній сфокусований доступний об'єкт при натисканні комбінації клавіш Ctrl Alt E.

По-перше, ми скористаємося рядками імпортування:

from accerciser.plugin import Plugin import gtk import pyatspi

Далі, ми створимо клас як похідний від базового класу Plugin і визначимо деякі обов'язкові атрибути класу:

class FocusSelect(Plugin): plugin_name = 'Focus Select' plugin_description = 'Allows selecting last focused accessible.'

Тепер ми перевизначимо метод init, у якому ви встановимо загальну клавіатурну дію для вибору останнього доступного об'єкта, зареєструємо засіб очікування на подію для події «focus» і встановимо для змінної екземпляра last_focused значення None.

def init(self): pyatspi.Registry.registerEventListener(self.accEventFocusChanged, 'focus') self.global_hotkeys = [('Inspect last focused accessible', self.inspectLastFocused, gtk.keysyms.e, gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK)] self.last_focused = None

Зауважте, що змінна екземпляра global_hotkeys є списком кортежів. Кожен кортеж є записом загальної дії клавіатурного скорочення, що складається з опису дії і бажаного методу для виклику, символу клавіш комбінації та маски модифікаторів клавіш.

У зворотному виклику події «focus» ми визначаємо змінну екземпляра last_focused доступним об'єктом, який щойно видав подію «focus».

def accEventFocusChanged(self, event): if not self.isMyApp(event.source): self.last_focused = event.source

У зворотному виклику дії клавіатурного скорочення ми оновлюємо загальний для програми вузол останнім фокусованим доступним об'єктом, якщо його було записано:

def inspectLastFocused(self): if self.last_focused: self.node.update(self.last_focused)

# Створення консольного додатка

Ми створимо консольний додаток для показу змін у фокусуванні, які видаються доступним об'єктом із роллю «кнопка» — пам'ятайте, що за допомогою Accerciser доволі просто перевірити роль будь-якого запису; ви можете виконати перевірку, наприклад, за допомогою панелі перегляду ієрархії програм.

Потрібні рядки імпортування:

from accerciser.plugin import ConsolePlugin import pyatspi

Далі, ми додаємо визначення класу із назвою та описом додатка:

class PushButtonFocus(ConsolePlugin): plugin_name = 'Push Button Focus' plugin_description = 'Print event when pushbutton get\'s focus.'

Ми перевизначаємо метод init додаванням засобу очікування на події реєстру:

def init(self): pyatspi.Registry.registerEventListener(self.accEventFocusChanged, 'focus')

У методі зворотного виклику буде виведено усі події кнопки.

def accEventFocusChanged(self, event): if event.source.getRole() == pyatspi.ROLE_PUSH_BUTTON: self.appendText(str(event)+'\n')

# Створення додатка панелі перегляду

Ми створимо додаток поля перегляду, який уможливлює швидке тестування дії «клацання» у доступних об'єктах, у яких передбачено підтримку інтерфейс Action AT-SPI і які мають дію із назвою «click». Це буде проста кнопка, як у відповідь на натискання виконуватиме дію «клацання» у доступному об'єкті.

Спочатку, декілька рядків обов'язкових імпортувань:

import gtk from accerciser.plugin import ViewportPlugin

Далі, визначення класу із назвою та описом:

class Clicker(ViewportPlugin): plugin_name = 'Clicker' plugin_description = 'Test the "click" action in relevant accessibles.'

Ми перевизначаємо метод init із додаванням певного графічного інтерфейсу і з'єднуємо зворотний виклик із сигналом для кнопки. Ми використовуємо контейнер вирівнювання для уможливлення центрування кнопки у вкладці додатка без зайвого заповнення кнопкою усього простору панелі додатка. Зауважте, що змінна екземпляра plugin_area містить gtk.Frame, який можна заповнити усіма віджетами додатка.

def init(self): alignment = gtk.Alignment(0.5,0.5,0,0) self.click_button = gtk.Button('Click me!') alignment.add(self.click_button) self.plugin_area.add(alignment)

self.click_button.connect('clicked', self.onClick)

self.show_all()

Ми також створили зручний метод, який повертає список підтримуваних дій поточного вибраного доступного об'єкта — якщо у ньому не передбачено підтримки інтерфейсу Action, він повертає порожній список:

def accSupportedActions(self): try: ai = self.node.acc.queryAction() except NotImplementedError: action_names = [] else: action_names = [ai.getName(i) for i in xrange(ai.nActions)] return action_names

У базовому класі додатків є метою, який називається onAccChanged і який викликають кожного разу, коли вибраний доступний об'єкт цільової програми змінюється. Ми перевизначимо його встановленням кнопки, яка реагуватиме лише, якщо поточний доступний об'єкт має дію «клацання»:

def onAccChanged(self, acc): has_click = 'click' in self.accSupportedActions() self.click_button.set_sensitive(has_click)

Метод зворотного виклику для «натискання» кнопки виконує дію «натискання» для доступного об'єкта. Оскільки цей зворотний виклик можна викликати, лише якщо кнопка є чутливою, нам не слід перейматися перевіркою, чи має поточний доступний об'єкт дію «клацання».

def onClick(self, button): ai = self.node.acc.queryAction() action_names = [ai.getName(i) for i in xrange(ai.nActions)] ai.doAction(action_names.index('click'))