Tworzymy frontend do Wake On Lan w PHP GTK

background image

2 / 2 0 0 5

Wszelkie prawa zastrzeżone. Rozpowszechnianie artykułu bez zgody Software Wydawnictwo Sp. z o.o. zabronione.

Software Wydawnictwo Sp. z o.o., ul. Lewartowskiego 6, 00-190 Warszawa, POLSKA.

redakcja@phpsolmag.org

background image

Projekty

PHP Solutions Nr 2/2005

www.phpsolmag.org

2

Projekty

PHP-GTK

PHP Solutions Nr 2/2005

www.phpsolmag.org

3

C

zęste uruchamianie wielu kom-
puterów jest bardzo męczące,
szczególnie, gdy są one rozsia-

ne po wielu pomieszczeniach w budynku.
Można jednak ułatwić tę czynność – słu-
żą do tego aplikacje typu Wake-On-Lan
(WOL), które budzą wszystkie lub wybra-
ne komputery znajdujące się w sieci lo-
kalnej na podstawie adresów MAC ich
kart sieciowych.

Wzięliśmy pod lupę jeden z takich

programów. Jego instalację opisaliśmy
w Ramce Instalacja Wake-On-Lan. Jest
to prosta aplikacja działająca w trybie tek-
stowym – aby ją uruchomić, trzeba w linii
poleceń wpisać

wakeonlan <adres _ MAC>

,

np.

wakeonlan 3F:34:00:AC:90:A0

i zdalny

komputer zostanie uruchomiony. Już to
jest powodem do radości – o niebo lepiej
przecież wprowadzić serię takich instruk-
cji, niż biegać po całym budynku! Dlacze-
go by jednak nie ułatwić sobie życia auto-
matyzując ten proces? Zrobimy to, wypo-
sażając to pożyteczne narzędzie w inter-

Za pomocą biblioteki PHP-GTK możemy tworzyć

profesjonalne aplikacje okienkowe przy użyciu

PHP. Wystarczy przećwiczyć ją na paru prostych

przykładach i zacząć pisać programy, do których

dawniej potrzebowalibyśmy znajomości C++ czy

Javy.

fejs graficzny (frontend), do napisania któ-
rego użyjemy PHP z biblioteką PHP-GTK.
Jest ona darmowa i dostępna na naszej
płycie oraz w Sieci (jej instalację opisali-
śmy w Ramce Instalacja PHP-GTK).

Dla wielu programistów PHP jest to

nowość – przyzwyczaili się bowiem, że
PHP to wyłącznie wygodny język skryp-
towy umożliwiający tworzenie zaawanso-
wanych stron WWW lub aplikacji interne-
towych. Niewielu natomiast zdaje sobie
sprawę z faktu, że po zainstalowaniu

Tworzymy frontend

do Wake-On-Lan w PHP-GTK

Jacek Niewęgłowski

W SIECI

NA CD

Na CD zamieściliśmy kody

źródłowe gotowego interfejsu,

aplikację wakeonlan oraz roz-

szerzenie PHP-GTK pod Win-

dows i Linuksa.

1. http://gtk.php.net

2. http://gtk.php.net/manual/en/

reference.php

3. http://oldgsd.lsd.di.uminho.pt./

jpo/software/wakeonlan/

4. http://www.gtk.org

Co należy wiedzieć...

Czytelnik powinien mieć podstawową

znajomość składni języka PHP. Przydat-

na też będzie wiedza z zakresu podstaw

programowania obiektowego, w tym po-

jęć klasa i obiekt.

Co obiecujemy...

Programista dowie się, jak stworzyć

graficzny interfejs do programu Wake-

On-Lan i zdobędzie wystarczającą wie-

dzę, aby samodzielnie tworzyć aplikacje

z wykorzystaniem PHP-GTK.

background image

Projekty

PHP Solutions Nr 2/2005

www.phpsolmag.org

2

Projekty

PHP-GTK

PHP Solutions Nr 2/2005

www.phpsolmag.org

3

PHP-GTK parser PHP może również

stać się potężnym narzędziem do budo-
wania w pełni funkcjonalnych, samodziel-
nych aplikacji okienkowych działających
zarówno pod kontrolą systemu Linux jak
i Windows.

Okno na dzień dobry

Tworzenie interfejsu graficznego (w skró-
cie GUI) przy użyciu PHP-GTK nie jest
zbyt trudne (co wynika m.in. z przejrzy-
stości biblioteki GTK). Czas jego wdroże-
nia zależy przede wszystkim od tego, jak
dobrze zaprojektujemy go przed przystą-
pieniem do programowania.

Najprostszy przykład zastosowania

PHP-GTK znajduje się na Listingu 1 – te
kilka linijek kodu to wszystko, czego po-
trzebujemy, aby wygenerować okienko
i ustawić jego podstawowe właściwości.
Efekt działania tego skryptu przedstawia
Rysunek 1.

Koncepcja

Nasz interfejs ma być funkcjonalny i pro-
sty w obsłudze. Aplikacja zewnętrzna Wa-
ke-On-Lan
ma być uruchamiana jednym
kliknięciem. Chcemy móc wpisywać adre-
sy MAC w okienku i gromadzić listę kilku
do kilkunastu ostatnio odwiedzanych, aby
następnie je wybierać. Lista powinna być
automatycznie ładowana przy uruchamia-
niu frontendu i zapisywana przy jego za-
mykaniu.

Musimy wziąć pod uwagę to, iż apli-

kacja Wake-On-Lan przesyła budzą-
ce zdalny komputer „magiczne pakiety”
przy pomocy protokołu UDP (ang. User
Datagram Protocol
) – nie mamy więc
żadnej gwarancji, iż zostaną dostarczo-

ne do adresata. Obowiązek zmniejsze-
nia ilości błędów spada więc na nas –
dlatego powinniśmy zaimplementować
sprawdzanie danych po stronie naszej
aplikacji, która automatycznie będzie in-
formować o błędach dotyczących forma-
tu adresu.

Podczas pisania naszego programu

będziemy dążyli do uzyskania efektu ta-
kiego jak na Rysunku 2. Cały kod two-
rzący interfejs umieścimy w jednym pliku
o nazwie wolgui.php.

Tworzymy interfejs

Każda aplikacja PHP-GTK musi zawie-
rać na końcu pliku z kodem instrukcję

gtk::main()

, która rozpoczyna główną

pętlę programu. Aby poprawnie zakoń-
czyć działanie aplikacji, trzeba wywołać
instrukcję

gtk::quit()

. Okienko jest pod-

stawowym obiektem zawierającym inne
elementy interfejsu (widgety, ang. wid-
gets
), zwanym kontenerem (ang. con-
tainer
).

Na Listingu 1 mamy już zalążek ko-

du tworzącego okienko – musimy go
tylko rozwinąć. Na początek usuwa-
my (albo blokujemy znacznikiem ko-
mentarza) instrukcję

$window->show _

all()

, którą należy umieścić po usta-

wieniu wszystkich elementów fronten-
du. Inicjujemy okienko, nadajemy mu
tytuł i ustawiamy jego parametry: poło-

żenie (zawsze na środku ekranu), sze-
rokość (stała), wysokość (automatycz-
na, zależna od zawartości okna), sze-
rokość ramki (margines wewnętrzny
między elementami okna a jego kra-
wędzią), możliwości skalowania (wyłą-
czamy całkowicie), a następnie decydu-
jemy, że zamknięcie okienka oznacza
przerwanie programu. Efekty naszych
dotychczasowych prac można obejrzeć
na Listingu 3.

Wypadałoby powiedzieć parę słów

o zamykaniu okna – skąd program ma
wiedzieć, że gdy to robimy, każemy mu
przerwać swoje działanie? Dzieje się to
dzięki połączeniu (ang. connecting) wy-
syłanego przez wydarzenie (ang. event)
zamknięcia okna sygnału (ang. signal)

destroy

z funkcją

shutdown()

(napisze-

my ją później), która wywołując

gtk::

quit()

przerywa działanie aplikacji. Sy-

gnały wysyła podczas interakcji z użyt-
kownikiem każdy element interfejsu wy-
stępujący w PHP-GTK, a kojarzone z ni-
mi funkcje (które są zwykłymi funkcjami

Rysunek 1.

Pierwsze okienko w PHP-

GTK

Listing 1.

Tworzenie okienka

w PHP-GTK

$window

= &

new

GtkWindow

()

;

$window

-

>

set_title

(

"Wake-On-Lan"

)

;

$window

-

>

set_usize

(

300, -1

)

;

$window

-

>

show_all

()

;

Czym jest adres MAC?

Adres MAC (ang. Media Access Control

address) to 48-bitowy, sprzętowy adres

karty sieciowej nadawany przez produ-

centa. Jest unikalny w skali światowej

(teoretycznie – niektóre nowsze karty

dają możliwość jego zmiany). Zapisu-

jemy go w postaci sześciu liczb 8-bito-

wych w systemie szesnastkowym (hek-

sadecymalnym), rozdzielonych znakami

dwukropka lub myślnikami – przykład:

A0:04:FC:0C:00:26.

Wymagania Wake-On-Lan

Na komputerze, z którego będziemy uruchamiać inne maszyny potrzebujemy jedynie za-

instalowanej aplikacji WOL. Jednak, aby cała operacja przebiegła pomyślnie, budzony

komputer musi spełniać pewne warunki sprzętowe. Oto one:

• płyta główna ATX z 3-pinowym złączem WOL,
• opcja LAN Wakeup włączona w BIOS-ie,
• karta sieciowa wspierająca WOL, prawidłowo podłączona do płyty głównej,
• zasilacz zgodny ze specyfikacją ATX 2.01.

Instalacja Wake-On-Lan

Istnieje kilka różnych aplikacji typu WOL. My skorzystamy z programu napisanego

w PERL-u przez José Pedro Oliveira, dostępnego pod adresem http://gsd.di.uminho.pt/

jpo/software/wakeonlan/downloads/wakeonlan-0.40.tar.gz

Aplikacja działa pod kontrolą systemu Linux, a jej instalacja sprowadza się do kilku

prostych kroków – ściągnij archiwum, przejdź do katalogu, w którym zostało zapisane

i wykonaj następujące polecenia:

tar -zxvf wakeonlan-0.40.tar.gz
cd wakeonlan-0.40
perl Makefile.PL
make
make install

Po wykonaniu tych czynności dostępne będzie polecenie

wakeonlan

. Sposób jego użycia

to:

wakeonlan <adres karty sieciowej komputera do obudzenia>

Przykład:

wakeonlan 00:09:7B:89:48:71

background image

PHP-GTK

Projekty

PHP Solutions Nr 2/2005

www.phpsolmag.org

4

PHP) określamy angielskim terminem
callbacks.

Przejdźmy teraz do tworzenia funk-

cji

shutdown()

. Wiemy już częściowo, co

ma ona robić – przerywać działanie pro-
gramu. Fajnie by było, gdyby zostawiała
po tym ślad w konsoli systemowej, z któ-
rej użytkownik wywoła skrypt – łatwiej
będzie stwierdzić, że program został za-
mknięty prawidłowo. Pamiętajmy, że nie
pracujemy w trybie CGI i naszym stan-
dardowym wyjściem jest nie ekran prze-
glądarki, tylko konsola – do niej więc funk-
cje takie jak

print()

czy

echo

będą kiero-

wać dane. Kod funkcji

shutdown()

prezen-

tujemy na Listingu 4.

Elementy interfejsu

Utworzenie i ustawienie okienka to jed-
nak dopiero początek. Oto lista elemen-
tów, które dopiero musimy zaimplemento-
wać w naszym frontendzie:

• etykieta Adres MAC, opisująca pole

tekstowe do wprowadzania adresu,

• pole tekstowe, w które użytkownik bę-

dzie mógł wpisać adres MAC budzo-
nego komputera,

• lista przechowującą ostatnio wprowa-

dzone adresy (historia),

• przycisk Obudź, wywołujący ze-

wnętrzną aplikację,

• przycisk Zamknij, kończący działanie

aplikacji,

• przycisk Wyczyść listę, pozwalający wy-

czyścić historię wpisywanych adresów.

Zaczniemy od utworzenia tych elemen-
tów, a dopiero później rozmieścimy je
w obszarze naszego okna. Każdy z wid-
getów jest zdefiniowany w odrębnej kla-
sie – tworzymy więc jego instancję czy-
li obiekt. Wszelkie parametry przekazu-
jemy albo przez jego konstruktor, albo
później, przy użyciu innych metod obiek-
tu. Na pierwszy ogień pójdzie etykieta

Adres Mac, zdefiniowana w klasie

Gtk-

Label

. Tworzymy jej instancję

$label

,

przekazując jednocześnie napis, który
ma się na niej ukazać, a następnie usta-
wiamy dodatkowy parametr – wyrówna-
nie tekstu.

Następnie utworzymy pole tekstowe

– obiekt klasy

GtkEntry

, który nazwiemy

$macaddress

. Pamiętajmy, aby umożliwić

użytkownikowi wpisywanie tekstu do nie-
go. Efekt prac widać na Listingu 5.

Zrobiliśmy już najprostsze elemen-

ty, czas na coś trudniejszego. Zajmij-
my się więc historią ostatnio wpisywa-
nych adresów, która będzie listą zawie-
rającą tylko jedną kolumnę o nagłówku
Ostatnio wywołane i umożliwiającą wy-
branie tylko jednego elementu pojedyn-
czym kliknięciem. Ma także dostosowy-
wać swoją szerokość do zawartości. Ża-
den problem, PHP-GTK dysponuje kla-

GtkCList

. Tworzymy jej obiekt nazy-

wając go

$clist

. Ustawiamy jej parame-

try dotyczące kolumn i wymiarów. Defi-

Rysunek 2.

Wygląd interfejsu

Listing 2.

Ładowanie rozszerzenia

PHP-GTK

if

(

!extension_loaded

(

'gtk'

)){

dl

(

'php_gtk.'

.PHP_SHLIB_SUFFIX

)

;

}

Wymagania PHP-GTK

Do poprawnego działania rozszerzenie PHP-GTK potrzebuje zainstalowanego PHP

4.3.x oraz biblioteki Gtk+ 1.2.6 lub nowszej (ale nie z serii Gtk+ 2.x). Aktualnie rozszerze-

nie w żadnym stopniu nie współpracuje z PHP5. W przyszłości autorzy planują dodanie

obsługi PHP5 i biblioteki Gtk+ z serii 2.x.

Instalacja PHP-GTK

Pod Linuksem zwykle mamy w systemie bibliotekę Gtk+, a jeśli nie, to znajduje się ona

wśród pakietów w dystrybucji. Można też ją ściągnąć ze stron GTK: http://www.gtk.org

i zainstalować. Następnie pobieramy archiwum PHP-GTK – z płyty załączonej do nume-

ru lub z witryny projektu PHP-GTK: http://gtk.php.net/, sekcja download. Potem wchodzi-

my do katalogu, w którym umieściliśmy ten plik i wydajemy następujące polecenia:

tar -zxvf php-gtk-1.0.1.tar.gz
cd php-gtk-1.0.1
./buildconfig
./configure –enable-php-gtk –disable-libglade
make
make install

Pod Windows sprawa jest jeszcze prostsza – wystarczy ściągnąć z Sieci lub przegrać
z naszej płyty archiwum PHP-GTK zawierające komplet skompilowanych pakietów, któ-
rych potrzebujemy: rozszerzenie PHP-GTK, bibliotekę GTK 1.2.x i parser PHP 4, a na-
stępnie rozpakować archiwum i postępować zgodnie z instrukcją umieszczoną w pliku
Readme.

Listing 3.

Zmodyfikowany kod tworzący okienko

// zainicjowanie okienka

$window

= &

new

GtkWindow

()

;

// nadanie mu tytułu

$window

-

>

set_title

(

"Wake-On-Lan"

)

;

// ustalenie szerokości ramki okienka

$window

-

>

set_border_width

(

10

)

;

// wyłączenie możliwości skalowania okna: zmniejszania, zwiększania
// i automatycznej minimalizacji do rozmiaru, przy którym widoczne są
// wszystkie jego elementy (każdy parametr może być true albo false)

$window

-

>

set_policy

(

false, false, false

)

;

// ustawienie szerokości okienka na 300 pikseli i wysokości na automatyczną

$window

-

>

set_usize

(

300, -1

)

;

// ustawienie okienka na środku ekranu (bez względu na rozdzielczość)

$window

-

>

set_position

(

GTK_WIN_POS_CENTER

)

;

// skojarzenie akcji zamknięcia okienka z wywołaniem funkcji
// shutdown(), która uruchamia instrukcję gtk::quit()

$window

-

>

connect

(

"destroy"

,

"shutdown"

)

;

background image

Projekty

PHP-GTK

PHP Solutions Nr 2/2005

www.phpsolmag.org

5

niujemy zdarzenia (było już o tej techni-
ce) na wypadek wybrania wiersza oraz
usunięcia jego zaznaczenia. Oba zda-
rzenia obsłuży callback

add _ to _ en-

trybox()

, wpisujący wybraną z listy po-

zycję do pola adresowego. To, co zrobi-
liśmy zawierają Listingi 6 i 7.

Z obiektów widocznych pozostaną

nam jeszcze trzy przyciski – Obudź, Za-
mknij
, Wyczyść listę. Każdy z nich sta-
nowi obiekt

GtkButton

. Do dwóch z nich

będziemy chcieli dodać skróty klawiszo-
we – w tym celu utworzymy obiekt kla-
sy

GtkAccelGroup

, który będzie je prze-

chowywał:

$keys = &new GtkAccelGroup();

Zaczniemy od przycisku Zamknij. Two-
rzymy go, ustawiając jednocześnie na-
pis, który ma się na nim znaleźć. Następ-
nie ustalamy, że po naciśnięciu (emituje
wtedy sygnał

clicked

) przycisk ma wy-

woływać przerywającą działanie progra-
mu funkcję

shutdown()

. Chcemy też, aby

użytkownik mógł zrobić to samo wciska-
jąc klawisz [Escape] – nic trudnego, moż-
na skojarzyć z przyciskiem skrót klawi-
szowy, używając metody

add _ accelera-

tor()

(Listing 8).

Przejdźmy teraz do przycisku Wy-

czyść listę. Tworzymy obiekt typu

Gtk-

Button

, nazywając go

$btnClear

i łączy-

my jego wciśnięcie z wywołaniem funk-
cji

clearlist()

, która usuwa historię wpi-

sywanych adresów – zarówno z obiek-
tu listy

$clist

, jak i zmiennej tablicowej

$macs

. Wynik naszych działań przedsta-

wiamy na Listingu 9.

Zdefiniujemy teraz przycisk Obudź,

który będzie wywoływał aplikację ze-
wnętrzną Wake-On-Lan. Nazwiemy go

$btnWake

(Listing 10). Ponieważ czyn-

ność przez niego powodowana jest naj-
ważniejsza w całej aplikacji, dobrze by
było, gdyby użytkownik mógł ją wywołać
klawiszem. A nawet jednym z dwóch kla-
wiszy – niech będą to [Enter] – na klawia-

turze głównej i numerycznej. Wiemy już,
jak przypisać skrót klawiszowy: wystarczy
wywołać funkcję

add _ accelerator()

. Tu

zrobimy to dwukrotnie.

Pamiętajmy, że uruchomienie tej

aplikacji to ostatnia czynność – najpierw
trzeba odczytać adres z pola adreso-
wego (

$macaddress

) i (przy pomocy wy-

rażeń regularnych) sprawdzić jego po-
prawność. Jeśli został wprowadzony
prawidłowo, nasz interfejs wywoła apli-
kację, o której mowa. Jeśli nie – oczom
użytkownika ukaże się okienko informu-
jące go o błędzie, a okno aplikacji zosta-
nie schowane. Jak to wykonamy? Jak
już wiemy, wciśnięcie przycisku gene-
ruje sygnał

clicked

. Połączymy go więc

z funkcją

checkvalidity()

, którą dopiero

utworzymy. Zawrzemy w niej wszystkie
powyższe czynności sprawdzające (Li-
sting 11). Należy nadmienić, że tym ra-

Pierwszy test

Przed skorzystaniem z funkcji i metod tego rozszerzenia powinniśmy zadbać o jeszcze

jeden mały drobiazg. Aby mieć pewność, że rozszerzenie zostało załadowane, napisze-

my kilka instrukcji, które to sprawdzą oraz w razie potrzeby załadują rozszerzenie.

Do sprawdzenia, czy rozszerzenie jest dostępne wykorzystajmy funkcję

exten-

sion _ loaded()

, podając jej jako parametr ciąg

gtk

. Funkcja ta zwróci wartość logiczną

TRUE

lub

FALSE

. Gdy okaże się, że rozszerzenia brakuje, użyjemy funkcji

dl()

, aby je za-

ładować. W systemach uniksowych rozszerzenie pliku z wykorzystywaną przez nas bi-

blioteką to .so, natomiast w Windows jest to .dll. Aby uniezależnić się od systemu ope-

racyjnego, możemy w funkcji

dl(),

zamiast wpisywania rozszerzenia pliku, użyć stałej

PHP _ SHLIB _ SUFFIX

, która przechowuje odpowiednie rozszerzenie. Kod ładujący roz-

szerzenie powinien znaleźć się na samym początku pliku (Listing 2).

Listing 7.

Kod funkcji add_to_entrybox()

function

add_to_entrybox

(

$clist

){

global

$macaddress

;

// metoda set_text() wpisuje treść do pola tekstowego, a get_text() –

// pobiera tekst wybranej z listy $clist pozycji o numerze

// przechowywanym przez atrybut tej listy – tablicę selection (lista

// wszystkich wybranych pozycji) pod indeksem 0

$macaddress

-

>

set_text

(

@$clist

-

>

get_text

(

$clist

-

>

selection

[

0

]

, 0

))

;

}

Listing 6.

Utworzenie listy przechowującej adresy

// w konstruktorze określamy: liczbę kolumn listy

(

parametr 1.

)

// i tablicę zawierającą nagłówki kolejnych kolumn (parametr 2.)

$clist

= &

new

GtkCList

(

1,

array

(

"Ostatnio wywołane:"

))

;

// ustawienie wybierania tylko jednej pozycji na liście

$clist

-

>

set_selection_mode

(

GTK_SELECTION_BROWSE

)

;

// szerokość automatyczna, wg rozmiaru okna (-1), wysokość 200 pikseli

$clist

-

>

set_usize

(

-1, 200

)

;

// zaznaczenie elementu na liście wysyła sygnał select_row
// i wywołuje funkcję add_to_entrybox()

$clist

-

>

connect

(

"select-row"

,

"add_to_entrybox"

)

;

// usunięcie zaznaczenia elementu wysyła sygnał unselect_row
// i wywołuje funkcję add_to_entrybox()

$clist

-

>

connect

(

"unselect-row"

,

"add_to_entrybox"

)

;

Listing 5.

Tworzenie etykiety – obiektu klasy GtkLabel i pola tekstowego

(GtkEntry)

// utworzenie obiektu etykiety i przekazanie napisu przez konstruktor

$label

= &

new

GtkLabel

(

"Adresy MAC:"

)

;

// dokładne wyrównanie tekstu

$label

-

>

set_justify

(

GTK_JUSTIFY_FILL

)

;

// utworzenie obiektu pola tekstowego

$macaddress

= &

new

GtkEntry

()

;

// ustawienie możliwości pisania tekstu (true – można, false – nie)

$macaddress

-

>

set_editable

(

TRUE

)

;

Listing 4.

Kod funkcji shutdown()

function

shutdown

(

){

print

(

"Zamykanie programu.

\n

"

)

;

gtk::main_quit

()

;

}

background image

PHP-GTK

Projekty

PHP Solutions Nr 2/2005

www.phpsolmag.org

6

zem nie tylko powiązaliśmy sygnał z cal-
lbackiem
, ale również przekazaliśmy do
niego odniesienie do obiektu

$macad-

dress

.

Natomiast będąc przy funkcji

check-

validity()

, zwróćmy uwagę na trzy rze-

czy. Pierwszą i najważniejszą jest wy-
wołanie uruchamiającej aplikację ze-
wnętrzną Wake-On-Lan funkcji

wake()

w przypadku, gdy adres jest poprawny.
Druga dotyczy użycia będącej kontene-
rem i obiektem niewidocznym dla użyt-
kownika tabeli porządkującej elementy
(obiekt klasy

GtkTable

). Po jej utworze-

niu i przypisaniu do okienka dodajemy
do niej elementy, które mają się w oknie
ukazać, określając położenie każdego
z nich (szczegóły w Ramce Rozmiesz-
czenie elementów w tabeli
). Jest to cał-
kiem wygodny sposób organizowania
widgetów. Trzecią sprawą, której należy

poświęcić trochę uwagi jest wywołanie
przedstawionej na tym samym Listingu
funkcji

warnclick()

. Zamyka ona dowolne

okienko przekazane jej przez parametr –
w tym przypadku, jest to okno z komuni-
katem o błędzie.

Można też zrobić, aby przycisk

Obudź był niedostępny (i nie dało się na
niego kliknąć), gdy pole adresowe jest
puste. Tylko po co? Czy nie wystarczy
potraktowanie pustego pola

$macaddress

jako błędnie wprowadzonego MAC-a?
Byłoby to poprawne, ale znacznie mniej
eleganckie. Jak to wykonać? Program
musi w jakiś sposób sprawdzać, że po-
le

$macaddress

nie jest puste i modyfiko-

wać właściwości przycisku Obudź. Zmia-
ny w polu tekstowym generują sygnał

changed

– trzeba go więc połączyć z od-

powiednią funkcją, która będzie włączać
lub wyłączać przycisk

$btnWake

i gotowe!

Wymaga to drobnej modyfikacji we frag-
mencie kodu tworzącego pole adresowe

$macaddress

(dodanie połączenia sygna-

łu) i utworzenia funkcji

check _ length()

.

Wdrożenie tego pomysłu widać na Li-
stingu 12.

Utworzymy teraz funkcję

wake()

. Jej

kod widnieje na Listingu 13. Pisaliśmy
już, iż spełnia ona najważniejszą w ca-
łym programie rolę, którą jest wywołanie
aplikacji Wake-On-Lan. Wspomnijmy, iż
używa ona do tego wbudowanej do PHP
funkcji

system()

. Przedtem jednak prze-

Rozmieszczenie elementów w tabeli

Ostatnie cztery parametry metody

attach()

obiektu klasy

GtkTable

określają pozycję,

w której ma być umieszczony element. Pierwsze dwa z nich określają pozycje w pozio-

mie, kolejne dwa – w pionie. Każda para określa zasięg “od-do” między krawędziami ko-

lumn i wierszy (po 2 krawędzie na każdy wiersz i tyle samo na każdą kolumnę).

Przykład z naszej aplikacji: chcemy umieścić element

$label

w jednej komórce znaj-

dującej się w pierwszym wierszu tabeli o pięciu wierszach i trzech kolumnach.

$table->attach($label, 0, 1, 0, 1);

Można to opisać w następujący sposób: “element

$label

umieścimy w tabeli

$table

mię-

dzy 0. i 1. krawędzią w poziomie i między 0. i 1. krawędzią w pionie”. Okno, którego frag-
mentem jest nasz przykład przedstawiamy na Rysunku 3. Jest to układ widgetów naszego
interfejsu z Rysunku 2, na który dodatkowo nanosimy siatkę tabeli. Widoczne tam wąskie
odstępy między kolumnami i wersami są traktowane tak samo, jak inne kolumny i wersy.

Rysunek 3.

Numeracja krawędzi tabeli

Listing 10.

Kod tworzący przycisk „Obudź”

// stworzenie nowego przycisku Obudź, wywołującego aplikację Wake-On-Lan

$btnWake

= &

new

GtkButton

(

"Obudź"

)

;

// przypisanie 1. skrótu klawiszowego (Enter na klawiaturze głównej)

$btnWake

-

>

add_accelerator

(

"clicked"

,

$keys

,GDK_KEY_Return,GDK_MOD2_MASK,0

)

;

// przypisanie 2. skrótu (Enter na klawiaturze numerycznej)

$btnWake

-

>

add_accelerator

(

"clicked"

,

$keys

,GDK_KEY_KP_Enter,GDK_MOD2_MASK,0

)

;

// połączenie wciśnięcia przycisku z funkcją checkvalidity() i przekazanie
// do niej odniesienia do pola $macaddress

$btnWake

-

>

connect

(

"clicked"

,

"checkvalidity"

,

$macaddress

)

;

$btnWake

-

>

set_sensitive

(

FALSE

)

;

Listing 9.

Kod tworzący przycisk czyszczący listę oraz funkcje clearlist()

// utworzenie przycisku

$btnClear

i nadanie mu etykiety Wyczyść

list

ę

$btnClear

= &

new

GtkButton

(

"Wyczyść listę"

)

;

// połączenie wciśnięcia $btnClear z funkcją clearlist()

$btnClear

-

>

connect

(

"clicked"

,

"clearlist"

)

;

function

clearlist

(

){

global

$clist

,

$macs

;

$clist

-

>

clear

()

;

$macs

=

array

()

;

}

Listing 8.

Przyciski

// utworzenie przycisku

$btnAbort

z etykietą Zamknij

$btnAbort

= &

new

GtkButton

(

"Zamknij"

)

;

// Przypisanie skrótu klawiszowego do przycisku $btnAbort (Zamknij). Parametry
// to po kolei: sygnał emitowany przez przycisk po naciśnięciu, nazwa obiektu
// klasy GtkAccelGroup, kod klawisza (kody są w plikach źródłowych PHP-GTK:
// ext/gtk+/php_gdk.c), maska klawiszy-modyfikatorów (alt,shift,ctrl – tu
// żadnego nie używamy). Ostatni parametr (wartość 0) nie jest używany.

$btnAbort

-

>

add_accelerator

(

"clicked"

,

$keys

,GDK_KEY_Escape,GDK_MOD2_MASK,0

)

;

// skojarzenie przycisku z funkcją shutdown()

$btnAbort

-

>

connect

(

"clicked"

,

"shutdown"

)

;

background image

Projekty

PHP-GTK

PHP Solutions Nr 2/2005

www.phpsolmag.org

7

wana w pliku, gdy tylko wyłączamy nasz
interfejs i automatycznie z niego łado-
wana, gdy go znów uruchamiamy. Stwo-
rzymy więc w tym celu funkcje:

write _

list()

, która będzie zapisywać dane

i

loadlist()

, która będzie je odczytywać.

Pierwszą rzeczą, która przychodzi na

myśl, jest wybór metody zapisu i odczy-
tu. Nasza lista adresów (zmienna

$macs

)

jest tablicą, więc ma swoją strukturę. Aby
ją bezproblemowo zachować, a potem
odtworzyć, użyjemy funkcji

serialize()

i

unserialize()

. Poddają one dane seria-

lizacji i deserializacji.

Listing 13.

Kod funkcji wake()

function

wake

(

$address

){

// zamiana liter w adresie na

// wielkie i dodanie znaku końca

// linii (CR), niezbędnego do

// uruchomienia aplikacji WOL

$address

=

strtoupper

(

$address

)

.

"

\n

"

;

// dodanie adresu do historii

add_to_list

(

$address

)

;

// wywołanie aplikacji WOL

system

(

"wakeonlan "

.

$address

)

;

}

Listing 12.

Kod funkcji check_

length() i połączenia sygnału

changed

function

check_length

(

$inputfield

){

global

$btnWake

;

// sprawdzanie, czy w polu

// tekstowym ($inputfield) jest

// tekst (długość >0). Pobieramy

// go metodą get_text()

if

(

strlen

(

$inputfield

-

>

get_text

())

>

0

){

// jeśli tak, ustawiamy

// przycisk Obudź na aktywny

$btnWake

-

>

set_sensitive

(

TRUE

)

;

}

else

{

// jeśli nie, ustawiamy

// Obudź na nieaktywny

$btnWake

-

>

set_sensitive

(

FALSE

)

;

}

}

// połączenie dokonywania zmian
// w polu $macaddress z wywołaniem
// funkcji check_length

$macaddress

-

>

connect

(

"changed"

,

"check_length"

)

;

Listing 11.

Kody funkcji checkvalidity() i warnclick()

function

checkvalidity

(

$button

,

$entry

){

global

$window

;

// odczytanie adresu MAC z pola adresowego

$address

=

$entry

-

>

get_text

()

;

// zamiana myślników w adresie na dwukropki

$address

=

str_replace

(

"-"

,

":"

,

$address

)

;

// sprawdzenie poprawności adresu przy użyciu wyrażeń regularnych

if

(

preg_match

(

"/^[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]

{2}:[0-9a-f]{2}:[0-9a-f]{2}

$

\b

/i"

,

trim

(

$address

))){

// jeśli jest poprawny, wywołujemy funkcję wake() (uruchamia aplikację WOL)

wake

(

trim

(

$address

))

;

}

else

{

// jeżeli MAC jest niepoprawny, to:

// ukrywamy okienka aplikacji

$window

-

>

hide

()

;

// tworzymy okienko $warnwindow, w którym będzie ostrzeżenie

$warnwindow

= &

new

GtkWindow

()

;

// ustawiamy tytuł okienka

$warnwindow

-

>

set_title

(

"WOL: Błąd"

)

;

// ustawiamy margines okienka

$warnwindow

-

>

set_border_width

(

10

)

;

// ustawiamy skalowalność okienka

$warnwindow

-

>

set_policy

(

true, false, false

)

;

// ustawiamy pozycję okienka (pośrodku ekranu)

$warnwindow

-

>

set_position

(

GTK_WIN_POS_CENTER

)

;

// ustawiamy rozmiar okienka (szerokość automatyczna, wysokość 80)

$warnwindow

-

>

set_usize

(

-1, 80

)

;

// tworzymy tabelę porządkującą i ustalamy liczbę wersów (2) i kolumn (3)

$tab2

= &

new

GtkTable

(

2, 3

)

;

// tworzymy etykietę zawierającą komunikat o błędzie

$errormsg

= &

new

GtkLabel

(

"Format wprowadzanego adresu MAC jest

nieprawidłowy !"

)

;

// włączamy zawijanie tekstu (ang. wrapping) w tej etykiecie

$errormsg

-

>

set_line_wrap

(

true

)

;

// definiujemy przycisk OK i łączymy go z funkcją warnclick() zamykającą

// okienko komunikatu i przywracającą okno aplikacji

$btnok

= &

new

GtkButton

(

"OK"

)

;

$btnok

-

>

connect

(

"clicked"

,

"warnclick"

, &

$warnwindow

)

;

// przypisanie tabeli porządkującej do obiektu okienka

$warnwindow

-

>

add

(

$tab2

)

;

// wstawienie etykiety i przycisku do tabeli porządkującej

$tab2

-

>

attach

(

$errormsg

, 0, 5, 0, 1

)

;

$tab2

-

>

attach

(

$btnok

, 2, 3, 2, 3

)

;

// pokazanie okienka i wszystkich jego elementów

$warnwindow

-

>

show_all

()

;

}

}

// funkcja zamykająca dowolne okienko i przywracającą okno główne

function

warnclick

(

$button

,

$win

){

global

$window

;

// zamknięcie (zniszczenie) okienka przekazanego przez parametr

$win

-

>

destroy

()

;

// ukazanie okna głównego aplikacji

$window

-

>

show

()

;

}

prowadza jeszcze dwie czynności – za-
mienia wszystkie litery w adresie na wiel-
kie (ze względów estetycznych) i dodaje
adres do historii (stąd się ona bierze) przy
użyciu funkcji

add _ to _ list()

. Funkcja

dodaje adres zawsze na początku listy
(jako najnowszy). Najpierw sprawdza, czy
dodawany MAC istnieje już w historii i do-

pisuje go tylko, jeśli nie. Pamiętajmy też,
że nie możemy przekroczyć maksymalnej
liczby obiektów na liście (10) – gdyby mia-
ło to nastąpić, to najstarszy adres zosta-
nie usunięty. Kod

add _ to _ list()

przed-

stawiliśmy na Listingu 14.

Jak już wcześniej wspomnieliśmy,

chcemy, aby historia adresów była zapisy-

background image

PHP-GTK

Projekty

PHP Solutions Nr 2/2005

www.phpsolmag.org

8

Pierwszy z tych procesów przetwa-

rza całą tablicę (dane i ich strukturę)
na formę, którą można zapisać w pli-
ku, a drugi jest jego odwrotnością. Wy-
korzystamy więc

serialize()

w funkcji

write _ list()

i

unserialize()

w

load-

list()

. Obie funkcje zostały przedsta-

wione na Listingu 15.

Teraz pora na implementację auto-

matycznego ładowania listy przy uru-

Listing 14.

Kod funkcji add_to_list()

function

add_to_list

(

$address

){

global

$macs

,

$clist

;

// oczyszczenie adresu ze znaków takich jak spacje i entery

$address

=

trim

(

$address

)

;

// zmienna określająca, czy adres znajduje się na liście (TRUE)

// czy nie (FALSE). Tu ustawiamy ją domyślnie na FALSE

$exists

= FALSE;

// tablica tymczasowa, do której przenosimy adresy, jeżeli lista

// jest już pełna i trzeba usunąć najstarszy element

$temp

=

array

()

;

// pętla sprawdzająca, czy dodawany adres jest już na liście

foreach

(

$macs

AS

$addr

){

// jeśli adres został znaleziony, to ustawiamy $exists na TRUE

if

(

$addr

===

$address

){

$exists

= TRUE;

}

}

// po zakończeniu pętli: jeśli funkcja nie znalazła dodawanego

// adresu na liście, to:

if

(

!

$exists

){

// jeżeli historia ma maksymalną zdefiniowaną liczbę linii (10)

if

(

count

(

$macs

)

== MAX_LINES

){

// to tworzymy tablicę tymczasową $temp i w pętli foreach

$temp

=

array

()

;

// przenosimy do niej wszystkie adresy oprócz najstarszego

// ze zmiennej $macs

foreach

(

$macs

AS

$key

=

>

$value

){

if

(

$key

<

(

MAX_LINES

)

&&

(

$key

>

0

)){

$temp

[

$key

-1

]

=

$value

;

}

}

// po czym dodajemy do niej ($temp) nasz nowy adres ($address)

$temp

[]

=

$address

;

// i przenosimy jej zawartość z powrotem do tablicy $macs

$macs

=

$temp

;

// jeżeli historia jest krótsza niż 10 pozycji

}

else

{

// to zwyczajnie dopisujemy do niej nowy adres

$macs

[]

=

$address

;

}

// sortujemy tablicę $macs

ksort

(

$macs

)

;

// czyścimy zawartość listy $clist

$clist

-

>

clear

()

;

// usuwamy zmienną $temp

unset

(

$temp

)

;

// przenosimy zawartość tablicy $macs do listy $clist

foreach

(

$macs

AS

$addr

){

$clist

-

>

prepend

(

array

(

$addr

))

;

}

}

}

chamianiu programu i jej zapisywa-
nia przy jego zamykaniu. W pierw-
szym przypadku, wstawimy odwołanie
do funkcji

loadlist()

w części głównej

programu, tuż przed instrukcją

gtk::

main()

. W drugim umieścimy wywoła-

nie

write _ list()

wewnątrz napisa-

nej wcześniej funkcji

shutdown()

, któ-

rą lekko zmienimy, co widać na Listin-
gu 16.

Układanka

Najwyższy czas na rozmieszczenie
wszystkich elementów w obrębie okien-
ka aplikacji. Musimy tylko zadbać o jeden
drobiazg – nasza lista

$clist

nie jest, nie-

stety, z definicji listą przewijalną. Dostęp-
ne na niej są tylko te elementy, które są
widoczne na ekranie – reszty nie można
nijak z niej wybrać.

Istnieje jednak proste rozwiązanie te-

go problemu – biblioteka PHP-GTK dys-
ponuje klasą

GtkScrolledWindow

, która

definiuje okienko przewijalne ze znanymi
wszystkim paskami. Umieszczenie naszej
listy w tym okienku (które zostanie po-
traktowane jako kontener) umożliwi nam
więc jej przewijanie. Stworzymy obiekt
o nazwie

$scwindow

i ustalimy, że okienko

ma być przewijalne tylko w pionie, a pa-
sek przewijania – pojawiać się tylko wte-
dy, gdy jest potrzebny (czyli, gdy jest wy-
starczająco dużo pozycji). Rozwiązanie to
przedstawiliśmy na Listingu 17.

Przejdziemy teraz do finalizacji na-

szej układanki – ułożymy widgety
w oknie głównym aplikacji. Podobnie,
jak w przypadku okienka informujące-
go o błędzie, także tutaj użyjemy do te-
go tabeli

GtkTable

. Nadamy jej 4 wersy

i 2 kolumny, przypiszemy do nich widge-
ty, po czym dodamy skróty klawiszowe
oraz instrukcję, o której wspominaliśmy
na samym początku –

$window->show _

all()

, która wyświetla na ekranie okien-

ko i wszystkie jego elementy. Widać to
na Listingu 18.

Tak oto, krok po kroku, skompleto-

waliśmy cały interfejs programu Wake-
On-Lan
.

Uruchomienie aplikacji

Spróbujmy teraz uruchomić naszą apli-
kację pod systemem Linux. Jak już wspo-
mnieliśmy, wystarczy w konsoli systemo-
wej wpisać

php wolgui.php

(przy założe-

niu, że ścieżka do interpretera PHP jest
zdefiniowana). Powinno ukazać się okien-
ko podobne do tego z Rysunku 1. Takie
uruchamianie programu nie należy jed-
nak do najwygodniejszych – usprawnij-
my więc je trochę. Wystarczy, że w pierw-
szej linijce skryptu (jeszcze przed znacz-
nikiem

<?php

) umieścimy odwołanie do

parsera PHP, jak w przykładzie:

#!/usr/

local/bin/php -q

Oczywiście, podana ścieżka dostępu

jest zależna od położenia parsera PHP
na dysku i może być inna – sprawdzimy
ją wydając polecenie

whereis php

(jeśli

background image

Projekty

PHP-GTK

PHP Solutions Nr 2/2005

www.phpsolmag.org

9

nic nie zwraca, to znaczy, że PHP nie
jest w ogóle zainstalowany!). Następnie,
komendą

chmod oug+x wolgui.php

zmie-

nimy uprawnienia dostępu do pliku wol-
gui.php
. Od tej pory, aby uruchomić apli-
kację, wystarczy w wierszu poleceń wpi-
sać jej nazwę.

Co dalej z PHP-GTK

Zaprojektowanie i wykonanie interfejsu
opisanego w tym artykule dość dokład-

nie pokazuje ideę programowania z wy-
korzystaniem PHP-GTK. Oczywiście,
możliwości tego rozszerzenia są du-
żo większe i nie sposób je tu wszystkie
opisać. Na szczęście, na stronie pro-
jektu, pod adresem http://gtk.php.net/
manual/en/reference.php

dostępna

jest znakomita dokumentacja (niestety
nie w języku polskim). Opisano w niej
dokładnie każdy dostępny widget –
wszystkie jego cechy, metody i emito-

wane sygnały. Zachęcamy więc do lek-
tury tego podręcznika oraz nauki PHP-
GTK i jego wdrażania w swoich projek-
tach. n

Listing 16.

Zmieniony kod funkcji shutdown()

function

shutdown

(

){

print

(

"Zamykanie programu.

\n

"

)

;

// serializacja listy i zapis do pliku

write_list

()

;

// przerwanie pętli głównej programu

gtk::main_quit

()

;

Listing 15.

Kody funkcji write_list() i loadlist()

function

write_list

(

){

global

$macs

;

// otwarcie pliku list.dat do zapisu (w)

$fp

=

fopen

(

"list.dat"

,

"w"

)

;

// serializacja (serialize()) i zapisanie (fputs()) danych w pliku

fputs

(

$fp

, serialize

(

$macs

))

;

// zamknięcie pliku

fclose

(

$fp

)

;

}

function

loadlist

(

){

global

$clist

,

$macs

;

// sprawdzenie, czy istnieje plik list.dat

if

(

file_exists

(

"list.dat"

)){

// jeśli tak, to czy da się go otworzyć do odczytu

if

(

$fp

=

fopen

(

"list.dat"

,

"r"

)){

// gdy jest otwarty, to odczytujemy go w pętli while linia po linii

while

(

!

feof

(

$fp

)){

$fline

.=

fgets

(

$fp

, 1024

)

;

}

// po czym dane są deserializowane, czyli zamieniane na zwykłą

// tablicę $macs

$macs

= unserialize

(

trim

(

$fline

))

;

}

// zamknięcie pliku

fclose

(

$fp

)

;

}

// wypełnienie listy $clist wartościami z $macs

foreach

(

$macs

AS

$value

){

$clist

-

>

prepend

(

array

(

$value

))

;

}

}

Listing 18.

Kod tworzący tabelę

i umieszczający w niej widgety

// utworzenie obiektu tabeli

$table

$table

= &

new

GtkTable

(

4, 2

)

;

// odstępy między rzędami
// (wersami) tabeli

$table

-

>

set_row_spacings

(

5

)

;

// odstępy między kolumnami tabeli

$table

-

>

set_col_spacings

(

5

)

;

// dodanie skrótów klawiszowych

$window

-

>

add_accel_group

(

$keys

)

;

// umieszczenie tabeli w oknie

$window

-

>

add

(

$table

)

;

// ustawienie w tabeli widgetów

$table

-

>

attach

(

$label

,

0, 1, 0, 1

)

;

$table

-

>

attach

(

$macaddress

,

2, 3, 0, 1

)

;

$table

-

>

attach

(

$scwindow

,

0, 3, 4, 5

)

;

$table

-

>

attach

(

$btnClear

,

0, 1, 6, 7

)

;

$table

-

>

attach

(

$btnAbort

,

0, 1, 8, 9

)

;

$table

-

>

attach

(

$btnWake

,

2, 3, 8, 9

)

;

// wyświetlenie na ekranie okienka
// i jego wszystkich elementów

$window

-

>

show_all

()

;

Listing 17.

Kod tworzący okno klasy

GtkScrolledWindow

// utworzenie okienka przewijalnego

$scwindow

=&

new

GtkScrolledWindow

()

;

// przewijalność okna: pozioma
// (wyłączona) i pionowa (automa-
// tyczna, włączana zależnie od
// rozmiaru zawartości)

$scwindow

-

>

set_policy

(

GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC

)

;

// dodanie do okienka listy $clist

$scwindow

-

>

add

(

$clist

)

;


Wyszukiwarka

Podobne podstrony:
Spis wszystkich opcji BIOS-u, Wake On LAN or PCI Modem, Wake On LAN or PCI Modem
TeamViewer Manual Wake on LAN pl
PHP Praktyczne wprowadzenie R 4 Wstęp do programowania Proste skrypty PHP
Jak wstawić do bazy danych kod PHP i potem wykonać go w momencie pobrania z bazy, PHP Skrypty
Jak przesłać ręcznie metodą POST dane do skryptu przetwarzającego formularze, PHP Skrypty
Jak zapisać do pliku zawartość tablicy, PHP Skrypty
MIN Tworzywa sztuczne (do egzaminu), Mechanika i Budowa Maszyn sem II, MIN, Sprawka
Jak zabezpieczyć własne strony przed pobieraniem ich programami do ściągania całych witryn, PHP Skry
Materiały z tworzyw sztucznych do izolacji cieplnych, Studia, II rok, Materiały Budowlane 2
Jak wysłać list do grup dyskusyjnych USENET, PHP Skrypty
MEN tworzy zespół do zmiany Karty nauczyciela, Awans, Awans zawodowy - nauczyciel mianowany
jak tworzyć piosenki do us
Informacje do zadań on line Ekonometria II magisterskie uzupełniające 2
Kofigurowanie kompótera do pracy w sieciach LAN
Z Łapinsk i Posłowie do metody on ja,czyli Dziennik i o Gombrowiczu
Podstawowym miejscem pracy operatora jest stanowisko obsługi wtryskarki do pracy przetwórstwa tworzy

więcej podobnych podstron