2004 02 Aplety dla GNOME [Programowanie]


dla programistów
Zobacz w:
Aplety dla GNOME
Marek Sawerwain
edną z ciekawszych funkcji nowoczesnego środowiska
pracy jest możliwość umieszczania na ekranie małych
programów nazywanych apletami. W wielu graficz-
J
nych środowiskach pracy, działających pod kontrolą
systemu X Window, istnieje możliwość umieszczenia takie-
go apletu.
Nie inaczej jest w GNOME, które od  pradawnych
wersji posiada taką cechę. Zastosowania takich apletów
wbrew pozorom są bardzo szerokie. Można w nich umiesz-
czać przydatne programy, np. do sprawdzania poczty albo
monitorowania stanu baterii w notebooku.
Napisanie apletu w przypadku GNOME nie jest zada-
niem trudnym, szczególnie w najnowszej wersji 2.4. Środo-
wisko GNOME zawsze oferowało API łatwe do opanowa-
nia. W tym artykule chciałbym przedstawić sposób two-
Rysunek 1. Konfiguracja APM w jądrze 2.4.23
rzenia takiego małego programu na praktycznym przykła-
dzie apletu przeznaczonego do monitorowania stanu bate- Jeśli APM jest obsługiwane przez nas system, to na ekranie
rii w komputerach przenośnych, czyli różnego rodzaju note- terminala zobaczymy następującą linijkę tekstu (są to infor-
bookach. macje odczytane z komputera stacjonarnego):
Artykuł, jak myślę, będzie tym bardziej przydatny,
ponieważ nawet na stronie GNOME Developer's Home 1.16 1.2 0x07 0x01 0xff 0x80 -1% -1 ?
Page osobiście nie mogłem odszukać aktualnych informacji
o tworzeniu apletów do najnowszej wersji 2.4 środowiska. Gdy plik apm nie istnieje w katalogu proc, można spróbo-
Istnieje tam podręcznik opisujący tworzenie apletów, ale wać poleceniem modprobe apm załadować moduł obsługi
z roku 1999, a od tego czasu GNOME znacznie się zmieni- tego standardu. Jeśli i ten krok nie powiedzie się, czeka nas
ło, na lepsze oczywiście. rekompilacja jądra.
W procesie konfiguracji jądra najważniejsza opcja to
Czy jądro systemu obsługuje APM?  Advanced Power Management BIOS support  w sekcji  Ge-
Zanim zaczniemy pisać sam aplet, należy odpowiedzieć
sobie na wyżej postawione pytanie. Znacząca większość
notebooków obsługuje oczywiście ten standard, jak rów-
Czym są aplety?
nież jądro Linuksa. Jeśli korzystamy z jądra zawartego Aplet to mały/niewielki program. Takie określenie pojawi-
w określonej dystrybucji, to zazwyczaj obsługa APM jest ło wraz z pierwszą wersją Javy. Zastosowanie apletów Javy
umożliwia dołączanie do strony WWW nawet bardzo skom-
włączona. W razie wątpliwości wystarczy wydać następu-
plikowanych programów. Pomimo tego, pojęcie apletu doty-
jące polecenie:
czy raczej małych, ale bardzo przydatnych programów, np.
przeznaczonych do sterowania odtwarzaniem płyt CD Audio.
cat /proc/apm
Typowym przykładem apletu jest nasz aplet do monitorowania
stanu baterii. Środowisko GNOME posiada kilkanaście przy-
datnych apletów, np. do sprawdzania, czy w skrzynce pocz-
towej znajdują się nowe listy. Oczywiście GNOME posia-
O autorze:
da gotowy aplet do monitorowania baterii. Stan baterii jest
Autor zajmuje się tworzeniem oprogramowania dla
przedstawiany graficznie, co powoduje, że kod zródłowy liczy
WIN32 i Linuksa. Zainteresowania: teoria języków pro-
prawie 40kB. Nasz aplet jest równie przydatny, choć to tylko
gramowania oraz dobra literatura. Kontakt z autorem:
autorzy@linux.com.pl. 4kB tekstu zródłowego.
58 luty 2004
aplety dla gnome
Listing 1. Postać pliku /etc/apm w zależności od typu
komputera i sposobu jego zasilania
Zawartość pliku dla komputera stacjonarnego:
1.16 1.2 0x07 0x01 0xff 0x80 -1% -1 ?
Dla komputera przenośnego
z zasilaniem zewnętrznym (220V):
1.16 1.2 0x02 0x01 0x03 0x09 92% 125 min
Dla komputera przenośnego z zasilaniem z baterii:
1.16 1.2 0x02 0x00 0x00 0x01 92% 122 min
neral setup . Warto wsparcie dla APM skompilować jako
moduł, tak jak pokazuje to Rysunek 1.
Odczytanie informacji o stanie baterii
Ponieważ plik /proc/apm to tylko jedna linia tekstu, to
zadanie odczytania informacji jest bardzo łatwe. Wystarczy
skorzystać z typowej funkcji do skanowania ciągu znaków,
np. sscanf albo plikowej odmiany fscanf.
Listing 1 prezentuje postać pliku /proc/apm w trzech
różnych przypadkach: dla komputera stacjonarnego, prze-
nośnego z zasilaniem z sieci 220V oraz z zasilaniem z bate-
rii. Nas najbardziej interesują trzy ostatnie wartości, np.
Tabela 1. Znaczenie poszczególnych parametrów APM z pliku
/proc/apm
Kolejna wartość z
Opis
pliku /proc/apm
driver_version, numer wersji sterownika
np. 1.16
apm_version major numer wersji standardu APM
Rysunek 2. Schemat czynności wykonywanych w aplecie
and minor, np. 1.2
 92% ,  122 oraz  min . Są to potrzebne nam informa-
apm_flags, np. 0x02 dodatkowe wartości apm
cje, czyli stopień naładowania baterii, przewidywany czas
ac_line_status, zasilanie zewnętrzne: wartość
pracy oraz jednostka, w jakiej mierzony jest czas pracy
np. 0x00 0x00 oznacz brak, a 0x01 zasi-
(zazwyczaj minuty). Dla komputera stacjonarnego te para-
lanie z sieci 220V
metry przyjmują wartości: -1 i znak zapytania. Z tego
battery_status, dodatkowe informacje o bate-
powodu dość łatwo rozróżnić, czy nasz komputer posiada
np. 0x00 riach nie wykorzystywane
baterie, czy też nie.
w naszym aplecie: jeśli kompu-
Procedura  wyciągnięcia informacji z pliku sprowadza
ter jest w nie wyposażony, przyj-
się jedynie do otwarcia pliku /proc/apm w trybie do odczy-
mie wartość 0x00, a przy ich
tu oraz zastosowanie funkcji fscanf. Prezentuje to Listing 2.
braku  0xff
W naszym aplecie będziemy jednak korzystać z gotowych
battery_flags, dodatkowa wartość o bateriach,
funkcji zawartych w plikach apmlib.c oraz apm.h, które
np. 0x01 np. czy są ładowane: pole przyj-  wieki temu zostały opracowane przez Rickarda E. Faitha.
muje w takim przypadku war-
tość 0x9
Zaczynamy pisać aplet
Pisanie apletu warto rozpocząć od krótkiej chwili refleksji
battery_percentage, stopień naładowania baterii,
i zastanowienia się, co ma przedstawiać nasz aplet. Ponie-
np. 92% a -1% przy ich braku
waż aplet ma pokazywać stan baterii w komputerach prze-
battery_time, przewidywany czas pracy na
nośnych, to najłatwiej będzie zrealizować to wyświetlając
np. 122 bateriach, a -1 przy ich braku
komunikaty tekstowe. Można oczywiście wykorzystać ele-
using_minutes, jednostka czasu
menty graficzne, lecz nasz aplet ma pełnić głównie funk-
np. min
cje edukacyjne.
www.linux.com.pl 59
dla programistów
Zobacz w:
Listing 3. Postać pliku (z usuniętymi tłumaczeniami)
Listing 2. Odczytanie parametrów z /proc/apm
GNOME_BatteryApplet.server
char driver_version[10];
int apm_version_major, apm_version_minor, apm_flags;
int ac_line_status, battery_status, battery_flags, battery_percentage; type="exe"
int battery_time; location="/opt/libexec/battery-applet-2">
char units[10];
memset(&units[0], 10, sizeof(char));
FILE *f=NULL;
f=fopen("/proc/apm", "r");

fscanf(f, "%s %d.%d %x %x %x %x %d%% %d %s\n", (char *) driver_version, value="Battery Factory"/>
&apm_version_major, &apm_version_minor, value="Battery Factory"/>
&apm_flags,

&ac_line_status, &battery_status, type="factory"
&battery_flags, location="OAFIID:GNOME_BatteryApplet_Factory">
&battery_percentage,
&battery_time, units);
if(strncmp(units, "min", 3)==1)
using_minutes=1;
else

using_minutes=0; value="Battery Charge Monitor"/>
Wewnętrzna architektura GNOME może przyprawić o solidny ból głowy początkującego programistę. Może to value="Monitor laptop's and
być nawet mur nie do pokonania. Poszczególne elemen- notebook's baterry remaining
ty GNOME 2.4 (dla tego środowiska piszemy nasz aplet) są power"/>
oparte o definicję obiektu z biblioteki GLIB. Do tego docho- dzi jeszcze standard CORBA, który poprzez BONOBO jest value="Utility"/>
stosowany w implementacji komponentów oraz modelu value="battstat.png"/>


dokument/widok. Ponieważ podstawowym językiem jest
C, a nie C++, to  obiektowość środowiska nie jest tak oczy-
wista jak w systemie, w którym do implementacji zastoso-
wano C++. Ma to jednak swoje zalety  GNOME 2.4 uru-
chamia się dosłownie w parę sekund, a KDE ponad pół
minuty (tak przynajmniej przedstawia się to na moim oso-
bistym komputerze).
Autorom  wielkiej stopy udało się stworzyć bardzo
łatwe do opanowania API, które pozwala tworzyć progra-
my w GNOME niemal bez wstępnej nauki. Widać to szcze-
gólnie w przypadku GTK+. Podobnie jest w przypadku
apletów. Skomplikowane mechanizmy zostały ukryte przed
programistą i może on skupić się na tworzeniu samego
apletu. Gdy istnieje potrzeba, zawsze można sięgnąć bez-
pośrednio do wewnętrznej architektury.
Zanim zaczniemy pisać aplet, warto wiedzieć, że
GNOME posiada specjalny program panel-test-applets. Przy
Rysunek 3. Obiekty apletu do monitorowania stanu baterii
pomocy tej małej aplikacji można testować działanie apletu.
60 luty 2004
aplety dla gnome
fejsów korzystamy, czyli utworzyć tzw. repo_ids. W każdym
Listing 4. Funkcja fabryki odpowiedzialna za wywołanie
aplecie wygląda to zawsze tak samo. Ważnym parametrem
funkcji tworzącej interfejs apletu
jest location, bowiem tu trzeba podać pełną ścieżkę do
pliku wykonywalnego apletu. W naszym przypadku jest to
gboolean battery_app_factory (PanelApplet *applet,
const gchar *iid, gpointer data) { katalog /opt/libexec/battery-applet-2  może to być również
gboolean retval = FALSE;
/usr/libexec. Lepiej utworzyć własny katalog, aby nie two-
if(!strcmp(iid, "OAFIID:GNOME_BatteryApplet ))
rzyć bałaganu w oryginalnych plikach GNOME. W przy-
retval=create_applet (applet);
padku jakichś kłopotów, łatwiej będzie usunąć plik z aple-
return retval;
tem.
}
Istotniejsza jest deklaracja drugiego obiektu o nazwie
OAFIID:GNOME_BatteryApplet, bowiem to on reprezentu-
GNOME podczas instalacji nowej wersji apletu nie wymaga je właściwy aplet. Zwróćmy uwagę na parametr loca-
restartu  należy zadbać, aby nie była uruchomiona żadna tion. O ile w poprzednim przypadku podaliśmy ścież-
kopia apletu, a wtedy można bez kłopotów podmienić plik kę do pliku, to tym razem podajemy identyfikator fabry-
binarny. ki, która utworzy obiekt apletu. Tutaj znów podajemy
Zanim zaczniemy pisać kod, trzeba zorientować się, zestaw interfejsów, które muszą znalezć się w definicji
jakie czynności będziemy wykonywać. Schemat operacji każdego apletu. Ważniejsze są dodatkowe atrybuty, takie
wykonywanych w aplecie prezentuje Rysunek 2. Zwróć- jak nazwa (name), opis (description) oraz kategoria
my uwagę na dwa pierwsze żądania. Są one wysuwane w panelu (panel:category). Wpisujemy tu nazwę
przez obiekt panel i nasz aplet musi na nie reagować. Auto- menu, w którym zostanie umieszczony aplet. Określi-
rzy GNOME uprościli podstawowe czynności, więc two- my też plik ikonki, która zostanie wyświetlona w menu
rzenie fabryki sprowadza się do zastosowania makra. Two- (plik battstat.png znajduje się w każdym GNOME,
rzenie apletu polega tylko na sprawdzeniu identyfikatora. bowiem jest to ikona dołączonego do systemu domyślne-
Naszym zadaniem będzie głównie implementacja funkcji go monitora stopnia naładowania baterii). Definicje tych
create_applet oraz update_status. parametrów w polskim tłumaczeniu, czyli z przyrostka-
mi  -pl , prezentują się następująco:
Przygotowanie pliku  server
Pierwszą czynnością, którą wystarczy wykonać tylko raz, jest przygotowanie specjalnego pliku o rozszerze- value="Monitoruje stan bateri"/>
niu server. Jego pełna nazwa to GNOME_BatteryAp- plet.server. W tym pliku znajdą się podstawowe informa- value="Monitor stanu baterii w komputerach przenosnych"/>
cje o naszym aplecie: pełna ścieżka oraz krótkie opisy i pozycja w menu apletów. Plik server to plik tekstowy value="Narzędzia"/>
w języku XML, którego treść przedstawia Listing 3.
W stosunku do wersji zamieszczonej na płycie CD, nie ma Gdy już dysponujemy napisanym plikiem, pozostaje go
w nim tłumaczenia na język polski  każdy atrybut, taki jak tylko przegrać do katalogu, np. /usr/lib/bonobo/servers,
name, description czy panel:category, powinien posiadać a mówiąc ogólnie, do miejsca, w którym znajdują się inne
swoją odmianę dla różnych języków. Jest to dość ważne, pliki o rozszerzeniu server.
bowiem jeśli GNOME będzie używać polskiego interfej-
su, to aplet może nie zostać umieszczony w menu albo Implementacja apletu
nie będzie dostępny opis, a nawet sama nazwa w menu W pisanym przez nas aplecie występują cztery obiekty,
(wyświetli się tylko pusta linia). które należy zaimplementować. Przede wszystkim należy
Utworzenie tych tłumaczeń jest bardzo proste. Parametr dokonać implementacji fabryki oraz utworzyć komponent
(bądz atrybut) z dowolnej sekcji rożni się przyrostkami, np. reprezentujący aplet. Prezentuje to Rysunek 3, na którym
name-pl oznacza nazwę obiektu w języku polskim, podob- znajduje się schemat logiczny obiektów naszego apletu.
nie description-pl oznacza opis w języku polskim. Dla Widać na nim także komponent reprezentujący panel, na
obiektu fabryki OAFIID:GNOME_BatteryApplet_Factory tłu- którym znajdzie się nasz aplet. Oczywiście tym obiektem
maczenia raczej nie mają dużego znaczenia, więc najlepiej nie musimy się zajmować, ponieważ to obiekt panel będzie
pozostać przy oryginalnych nazwach. ładował nasz aplet.
Struktura pliku server wymaga obecności defini- Jak wcześniej napisałem, implementacja fabryki spro-
cji dwóch serwerów, w tym tzw. fabryki, która utworzy wadza się do zastosowania makra. Podobnie jest w przy-
obiekt apletu. padku obiektu apletu  w rzeczywistości jest to tylko
Definicja fabryki jest obowiązkowa, ale ponieważ do identyfikator, który służy do wywołania funkcji create_
definicji wystarczy zastosowanie odpowiedniego makra, applet (w niej następuje utworzenie interfejsu apletu).
my nie będziemy się tym szeroko zajmowali. W pliku server W tej funkcji następuje także jeszcze jedna istotna czyn-
wystarczy podać nazwę fabryki oraz opisać, z jakich inter- ność. Otóż rejestrujemy w niej następną funkcję update_
www.linux.com.pl 61
dla programistów
Zobacz w:
cy obiekt apletu, to nastąpi wywołanie następnej funkcji
Listing 5. Tworzenie interfejsu apletu
create_applet, tworzącej interfejs apletu. Funkcja realizu-
jąca takie zadanie o nazwie battery_app_factory zosta-
gboolean create_applet(PanelApplet *applet) {
ła przedstawiona na Listingu 4. Jak widać, sprawdza się
GtkWidget *w, *vbox, *hbox;
w = GTK_WIDGET(applet);
tam tylko, czy identyfikator przekazywany przez iid jest
gtk_widget_realize(w);
różny od identyfikatora obiektu apletu. Jeśli tak jest, to
is_apm=0;
należy utworzyć ten obiekt. W każdym innym przypad-
if(apm_exists()==0) is_apm=1;
ku będzie to oznaczać, że obiekt apletu został już wcze-
vbox=gtk_vbox_new(FALSE,1);
śniej utworzony.
hbox=gtk_hbox_new(FALSE,1);
label=gtk_label_new(NULL);
Zadaniem ostatniego argumentu makra PANEL_APPLET_
g_signal_connect(G_OBJECT(label), "destroy",
BONOBO_FACTORY jest przekazanie dodatkowych informacji,
G_CALLBACK(destroy_monitor), NULL);
które pózniej zostaną przekazane funkcji create_applet.
bat_status=gtk_label_new(NULL);
W naszym przypadku nie ma takiej potrzeby, więc podawa-
mesg=gtk_label_new(NULL);
na jest wartość NULL.
gtk_box_pack_start(GTK_BOX(vbox), label, 1,1,0);
// pozostałe operacje pakowania
gtk_container_add(GTK_CONTAINER(w), hbox);
Tworzenie interfejsu  funkcja
timer=gtk_timeout_add(1000, update_status, NULL);
create_applet
gtk_widget_show_all(w);
Gdyby omawiać zawartość funkcji tworzącej interfejs
panel_applet_setup_menu(PANEL_APPLET(applet),
apletu nie wskazując, iż chodzi o aplet, to można by
xml_dsc, battery_menu_verbs, applet);
return TRUE;
o niej powiedzieć, że jest to typowa funkcji tworząca wid-
}
gety dla aplikacji GTK+. Nasz aplet wszystkie komunikaty
przekazuje w formie tekstowej, dlatego w funkcji tworzy-
my tylko etykiety, odpowiednio umieszczając je w  pudeł-
status, której zadaniem jest uaktualnianie naszego apletu, kach . Ustalaniem treści komunikatów zajmuje się funkcja
tak aby użytkownik komputera widział zmieniający się update_status.
stan naładowania baterii. W funkcji create_applet sprawdzamy, czy program
może korzystać z APM. Za test odpowiedzialna jest funkcja
Implementacja fabryki apm_exists, która pochodzi z pliku apmlib.c.
Cały proces implementacji fabryki sprowadza się do zasto- Ze względu na specyfikę naszego apletu należy cyklicz-
sowania jednego makra. Najważniejsze są oczywiście para- nie odświeżać informacje, które wyświetla. Z tego powodu
metry, a wygląda to następująco: rejestrujemy funkcję update_status funkcją gtk_time-
out_add. Pierwszym parametrem określamy czas odświeża-
PANEL_APPLET_BONOBO_FACTORY nia w milisekundach. Podana wartość 1000 oznacza jedną
("OAFIID:GNOME_BatteryApplet_Factory", sekundę. Wywołanie wygląda tak:
PANEL_TYPE_APPLET,
"battery", timer=gtk_timeout_add(1000, update_status, NULL);
"0",
(PanelAppletFactoryCallback)battery_app_factory, Oczywiście podczas usuwania apletu z panelu należy
NULL) usunąć zarejestrowaną funkcję. Z tego powodu do
jednej z etykiet podłączana jest obsługa sygnału destroy.
Jak widać, mamy sześć parametrów. Jako pierwszy poda-
jemy identyfikator naszej fabryki  jest on oczywiście
identyczny z identyfikatorem podanym w pliku server.
Potem musimy podać typ obiektu, który jest tworzo-
ny przez fabrykę. Tutaj znów korzystamy z gotowej pre-
definicji i podajemy PANEL_TYPE_APPLET. W trzecim para-
metrze podajemy identyfikator obiektu  może to być,
tak jak w przykładzie, nazwa naszego apletu albo nazwa
pliku binarnego. Następny parametr powinien zawie-
rać numer wersji apletu. W naszym przypadku jest to
po prostu zero, ale można w tym miejscu podać numer
wersji, np.  1.0 .
W piątym co do kolejności parametrze należy podać
funkcję, która zostanie wywołana w momencie tworzenia
fabryki. Ta czynność jest bardzo istotna, ponieważ gdy
fabryce zostanie przekazany identyfikator reprezentują- Rysunek 4. Aplet w  akcji
62 luty 2004
aplety dla gnome
Pod koniec budowania interfejsu apletu rejestrowane jest
Listing 6. Tworzenie interfejsu apletu
również menu, które można uzyskać klikając prawym przy-
ciskiem na aplecie. Nasz aplet nie oferuje wyrafinowa-
gint update_status(gpointer d) {
apm_info ai; nych możliwości, więc w dodatkowym menu znajduje się
char txt[127];
tylko opcja  About . Oprócz opcji  About , w wyświetlo-
if(is_apm==1){
nym menu znajdują się trzy inne domyślne opcje, zawsze
apm_read(&ai);
obecne w każdym aplecie, takie jak  usuń z panelu ,  zablo-
if(ai.ac_line_status==1)
kuj (blokowanie pozycji apletu) oraz  przesuń .
gtk_label_set_text(GTK_LABEL(label),
"Zasilanie AC"); Chcąc dołączyć własne opcje do menu apletu, należy
else
przygotować opis elementów menu jako tabelę o typie
gtk_label_set_text(GTK_LABEL(label),
BonoboUIVerb. Tabela dla naszego apletu przedstawia się
"Zasilanie z baterii");
następująco:
if((ai.battery_flags & 0x8)==1){
gtk_label_set_text(GTK_LABEL(bat_status),
"Aadowanie baterii"); static const BonoboUIVerb battery_menu_verbs [] = {
}
BONOBO_UI_UNSAFE_VERB ("BatteryAbout", about_win),
if(ai.battery_percentage==-1){
BONOBO_UI_VERB_END
gtk_label_set_text(GTK_LABEL(bat_status),
};
"Brak baterii");
}
else Element menu jest reprezentowany przez makra BONOBO_UI_
{
UNSAFE_VERB, w którym mamy tylko dwa parametry: symbo-
sprintf(&txt[0],"stopien naładowania %d%%",
liczną nazwę oraz nazwę funkcji, która zostanie wywołana,
ai.battery_percentage);
jeśli dana opcja zostanie wskazana przez użytkownika.
gtk_label_set_text(GTK_LABEL(bat_status),
GNOME oferuje dość sporo możliwości w deklaracji
&txt[0]);
if(ai.battery_percentage>50) wyglądu menu, więc opis, jaka ikonka ma się pokazać
sprintf(&txt[0], "oraz sam tekst w menu określa się przy pomocy języka
weight=\"bold\" color=\"black\">
XML. Opis dla naszej opcji  About przedstawia się nastę-
OK
");
pująco:
if(ai.battery_percentage>=25 && ai.battery_
percentage<=50)
sprintf(&txt[0], "
weight=\"bold\" color=\"blue\">
Średni stan\n naładowania
");
_label="_About..."
if(ai.battery_percentage<25)
pixtype="stock" pixname="gnome-stock-about"/>
sprintf(&txt[0], "
weight=\"bold\" color=\"red\">
UWAGA!!! Baterie\n bliskie
rozładowania!!!
");
W atrybucie verb musimy podać taką samą wartość jak we
gtk_label_set_justify (GTK_LABEL(mesg),
wcześniej zadeklarowanej tablicy. Rejestrację tego menu
GTK_JUSTIFY_CENTER);
dokonuje funkcja panel_applet_setup_menu. W drugim
gtk_label_set_markup(GTK_LABEL(mesg),
argumencie przekazujemy zmienną xml_dsc typu gchar*
,
&txt[0]);
} zawierającą opis w XML-u, a w trzecim nazwę zmiennej
}
zawierającej tabelę z elementami menu. Wywołanie funk-
else {
cji jest następujące:
gtk_label_set_text(GTK_LABEL(label), "Brak
dostępu do APM!!!");
panel_applet_setup_menu(PANEL_APPLET(applet),
}
} xml_dsc, battery_menu_verbs, applet);
Istnieje także możliwość zdefiniowania menu w pliku.
Funkcja wywołana w wyniku odpowiedzi na ten sygnał Na płycie CD znajduje się plik xml, który definiuje takie
wyrejestruje obsługę odświeżania oraz dodatkowo menu. Rejestrację menu opisanego w pliku wykonuje się
wygeneruje sygnał dzwiękowy. Treść tej funkcji jest przy pomocy funkcji panel_applet_setup_menu_from_file,
bardzo krótka: podając w jednym z argumentów nazwę pliku. Sam plik
definiujący menu o nazwie GNOME_BatteryApplet.xml
void destroy_monitor(GtkWidget *w, gpointer d) { należy umieścić np. w katalogu /usr/share/gnome-2.0/ui.
gtk_timeout_remove(timer); Zawartość funkcji about_win nie będzie tu przytaczana,
gdk_beep(); ponieważ tworzy ona tylko okno (funkcja gnome_about_
} new), wykorzystując dostępny w GNOME widget okna infor-
macyjnego.
www.linux.com.pl 63
dla programistów
Zobacz w:
Funkcja update_status
Dzięki cyklicznym wywołaniom tej funkcji nasz aplet dobrze pełni swoją rolę,
bowiem pozwala na czujne śledzenie stanu naładowania baterii (działający aplet
można zobaczyć na Rysunku 4). Jak postanowiliśmy wcześniej, ta funkcja jest
wywoływana raz na sekundę. Jej działanie polega tylko na odczytaniu stanu APM
oraz uaktualnieniu wartości etykiet. Ponieważ GNOME oferuje formatowanie tekstu
przy pomocy znaczników, to wykorzystamy tę możliwość, aby wytłuścić etykietę
i nadać jej kolor czerwony, gdy stan baterii jest bardzo niski, niebieski, gdy stan
będzie średni, bądz czarny, gdy stopień naładowania baterii jest wysoki.
Pełny kod tej funkcji zawiera Listing 6. Odczytanie parametrów
z pliku /etc/apm realizuje funkcja apm_read, pochodząca z pliku apmlib.c. Następ-
nie, w zależności od stanu poszczególnych pól, ustalane są komunikaty w etykie-
tach. Jedna z etykiet pokazuje komunikat w zależności od stopnia naładowania
baterii zmieniając także kolor. Do ustalenia odpowiedniego koloru trzeba zastoso-
wać znacznik span. Dla niskiego stanu, czyli dla stanu naładowania baterii poniżej
25%, przygotowanie ciągu formatującego wygląda następująco:
sprintf(&txt[0], "
UWAGA!!! Baterie\n bliskie rozładowania!!!
");
W ciągu formatującym możemy stosować również sekwencje ESCAPE, np. \n,
która poprawnie zostanie zinterpretowana. W znaczniku zastosowaliśmy atrybuty
weight oraz color. Tak przygotowany komunikat wyświetlamy na ekranie stosując
funkcję gtk_label_set_markup zamiast gtk_label_set_text. W kodzie używamy
funkcji gtk_label_set_justify, aby wyśrodkować tekst w etykiecie.
Instalacja apletu
Po przygotowaniu kodu zródłowego apletu, możemy przystąpić do kompilacji,
którą dokonujemy następującym poleceniem:
S
gcc -o battery-applet-2 battery_app.c apmlib.c `pkg-config
--cflags --libs libgnomeui-2.0 libgnome-2.0 libpanelapplet-2.0`
Po udanej kompilacji plik binarny kopiujemy do katalogu, który został wyszcze-
gólniony w pliku server. Natomiast sam plik server, czyli GNOME_BatteryAp-
plet.server do katalogu /usr/lib/bonobo/servers. Katalog docelowy także może
zostać zmieniony. Wymaga to już niestety modyfikacji plików konfiguracyjnych
podsystemu bonobo-activation. Konfiguracja jest zapisana w pliku o nieco długiej
ścieżce: /usr/etc/bonobo-activation/bonobo-activation-config.xml.
Po uruchomieniu środowiska GNOME, aplet powinien być dostępny z menu
apletów wywoływanych prawym przyciskiem myszy nad dowolnym panelem.
Podsumowanie
Tworzenie apletów w GNOME nie wymaga specjalnych zabiegów poza przygotowa-
niem dodatkowych plików oraz użyciu makra zamiast funkcji main (makro można
pominąć i napisać stosowny kod samodzielnie). Pozostałą część apletu pisze się
w taki sam sposób, jak zwykłą aplikację GNOME czy GTK+. Ponadto, nasz aplet, cho-
ciaż napisany dla wersji 2.4, powinien bez kłopotów pracować także w wersji 2.2.
W Sieci:
" Główna strona GNOME:
http://www.gnome.org/
" Strona przeznaczona dla programistów piszących w GNOME:
http://developer.gnome.org/
64 luty 2004


Wyszukiwarka