Od Redakcji: artykuł pochodzi z marcowego wydania Linux Magazine. Kompletną listę artykułów możecie znaleźć na stronach miesięcznika.
Aplikacje oparte na interfejsie graficznym są miłe dla oka, ale o wiele trudniejsze do stworzenia niż prosty skrypt powłoki. Jeżeli podoba nam się prostota skryptów, jednak lubimy trochę więcej wsparcia graficznego, Zenity (dla środowiska Gnome) i KDialog (dla KDE) to para narzędzi, o których powinniśmy wiedzieć. Ci podręczni pomocnicy pozwolą nam zintegrować graficzne okna dialogowe ze skryptami.
Okna dialogowe proszą użytkownika o podanie danych, wyświetlają informacje lub po prostu pokazują postęp wykonania procesu. Zenity i KDialog również potrafią wyświetlać komunikaty błędów i ogólne informacje w formie okien, mogą sprawić, że już nigdy nie będziemy musieli skrupulatnie wpisywać ścieżek do plików; zamiast tego będziemy mogli użyć przeglądarki systemu plików.
Zaczynamy
Zenity [1] jest domyślnie dołączane do Gnome w openSUSE, Ubuntu i kilku innych dystrybucjach. KDialog często jest domyślnie instalowany wraz z KDE. Jeżeli nasza dystrybucja nie zawiera tych narzędzi, zainstalujmy pakiet kde4-dialog lub zenity. Jeśli piszemy skrypty, których będą używać także inni, na ich komputerach musi być zainstalowane Zenity albo KDialog. Dobrze byłoby, gdyby nasz skrypt przeprowadzał test na obecność tych programów, zanim wykona ich komendy.
Zenity w akcji
Dobry na start jest skrypt powłoki zawarty w Listingu 1. Przyjmując, że zapisaliśmy plik skryptu jako zenity, by nadać mu prawa do wykonania, wpisujemy chmod u+x zenity, a potem uruchamiamy go poleceniem ./zenity. Powinniśmy zobaczyć suwak podobny do tego na Rysunku 1. Ponieważ okno dialogowe nie ma nazwy i nie został ustawiony także opis suwaka, Zenity użyje domyślnych etykiet.
Listing 1: Prosty skrypt Zenity
#!/bin/sh zenity --scale
Jak możemy zauważyć, dostępne są także pola wejściowe. Bash czyta ich zawartość po kliknięciu OK. Przykładem jest pole --entry. By przekazać Bashowi wartość liczbową, używamy suwaka (--scale). Opcja --list umożliwia umieszczenie informacji w liście i ich sortowanie. Wskaźnik postępu staje się przydatny, kiedy tylko chcemy znać postęp wykonania zadania, na przykład podczas przeszukiwania. Najpierw jednak popatrzmy na podstawy.
Budujemy
Aby zatytułować okno, możemy użyć opcji --title. Listing 2 pokazuje, jak umożliwić użytkownikowi wybór liczby między 1 (--min-value=1) a 10 (--max-value=10) przy domyślnej wartości 5 (--value=5). Rezultat widać na Rysunku 1.
Rysunek 1: Suwak pozwala użytkownikowi graficznie wybrać liczbę.
Listing 2: Wybieranie liczb za pomocą suwaka
zenity --scale --title "Suwak" --text "Poprzesuwaj troszkę..." --min-value=1 --max-value=10 --value=5
Do suwaka możemy podać tylko ograniczony zestaw parametrów: man zenity ma osobną sekcję Scale Options, która opisuje opcje działające razem ze --scale. Na przykład pole --warning wspiera jedynie tekst i łamanie linii.
Niektóre opcje, aby zadziałały, muszą wystąpić w połączeniu z odpowiednimi komendami. Komendy spisane poniżej wyświetlają pliki znajdujące się w folderze i sortują je alfabetycznie, kiedy klikamy na Pokaż zawartość katalogu (Rysunek 2):
ls | zenity --list --column "Pokaż zawartość katalogu"
Rysunek 2: Zenity wyświetla zawartość folderu i sortuje listę alfabetycznie, kiedy klikamy na „Pokaż zawartość katalogu”.
Chociaż Zenity pozwala nam szybko zbudować graficzne menu, nie zajmie się za nas projektowaniem logiki programu. Musimy więc użyć instrukcji warunkowych, żeby ustalić, co ma się stać, gdy użytkownik kliknie na Tak, lub na Nie. Okna dialogowe Zenity i KDialog zazwyczaj mają zdefiniowane dwie zwracane wartości: rezultat pozytywny (Tak) zwraca 0, a negatywny (Nie) – 1. Trzeci rezultat, na przykład Anuluj z KDialog, zwraca 2. Możemy budować instrukcje warunkowe i sprawdzać te wartości.
W środowisku KDE
Użytkownicy narzędzia KDialog mają do dyspozycji podobne opcje tworzenia graficznych okien dialogowych. KDialog posiada kilka dodatkowych okien, których nie ma w Zenity. Na przykład aby potwierdzić usunięcie pliku, wpisujemy:
kdialog --yesno "Czy na pewno chcesz usunąć ten plik?"
Pojawia się pytanie w oknie dialogowym wraz z przyciskami Tak i Nie. Jeśli chcemy dodać tytuł, po prostu używamy opcji --title (Rysunek 3)
kdialog --title "Tak czy nie?" --yesno "Czy na pewno chcesz usunąć ten plik?"
Rysunek 3: KDialog szybko generuje okno z zapytaniem, jednak nie podoba mu się, jeśli nie ustawiliśmy żadnego tekstu.
W przeciwieństwie do Zenity programowi KDialog nie podoba się, jeśli po prostu wpisujemy kdialog --yesno bez dodawania żadnego tekstu – aplikacja nie wygeneruje domyślnych etykiet.
Gdy wpisujemy tekst do pola wejściowego, zwykle jest on przekazywany do konsoli, czyli na standardowe wyjście. Możemy jednak przekierować wynik do pliku – na przykład plik1.txt (Listing 3, wiersz 1.). Możemy także przekazać wynik do zmiennej (Listing 3, wiersz 2. i 3.).
Listing 3: Przekazywanie wyniku do zmiennej
kdialog --inputbox "Proszę wpisać tu jakiś tekst:" > plik1.txt zmienna=$(kdialog --inputbox "Proszę wpisać jeszcze jakiś tekst:") echo $zmienna
Do wspomnianych wyżej komunikatów możemy dodać także opcję --dontagain, która zapewnia, że KDialog nie będzie cały czas powtarzał pytania. Tryb ten dodaje pole wyboru z etykietą Nie pytaj ponownie.
kdialog --dontagain rememberfile:decision --yesno "Czy na pewno chcesz usunąć ten plik?"
Wpis rememberfile:decision zapewnia, że okno dialogowe zapamięta nasz wybór. KDialog tworzy plik o nazwie rememberfile w katalogu ~/.kde/share/config/ i umieszcza tam nasz wybór pod zmienną decision, co pokazuje poniższy test:
$ cat ~/.kde/share/config/§§ rememberfile [Notification Messages] decision=yes
W tym wypadku skrypt sam wybiera odpowiedź Tak, przy próbie ponownego wyświetlenia tego pytania. Okna dialogowe programu KDialog mają jeszcze kilka opcji, którym przyjrzymy się za chwilę. Jeśli nie będziemy mogli sobie z czymś poradzić, szczegóły znajdziemy na stronie manuala (man kdialog) oraz w pomocy programu KDialog [2].
Opcja --passivepopup pozwala wyświetlić krótki komunikat. Wraz z dialogiem pokazuje się okienko, które przekazuje użytkownikowi jakąś informację (Rysunek 4). Po tekście, który ma być zawarty w okienku, powinna znaleźć się liczba określająca czas, przez jaki ma być ono widoczne (w Listingu 4, w wierszu 1. czas został ustawiony na pięć sekund). Sekwencja /n łamie linię, aby zapobiec rozciągnięciu się tekstu na całym ekranie.
Rysunek 4: Użytkownik widzi informację bez utraty aktywności w obecnym miejscu.
Aby wybrać z dysku konkretny plik, dobrym sposobem jest użycie opcji --getopenfilename. Zwraca ona bezwzględną ścieżkę do pliku, na przykład /home/user/piosenka.mp3. To samo potrafi także parametr --getopenurl, który zwraca URL: file://home/user/piosenka.mp3. Przykładowo, możemy go użyć, jeśli chcemy otworzyć adres FTP. Odpowiednikami tych opcji zapisującymi pliki są --getsavefilename i --getsaveurl.
Aby pozwolić na otwarcie jedynie wybranych typów plików – na przykład ścieżek dźwiękowych w formacie MP3 – trzeba po prostu dodać parametr do odpowiedniej opcji (Listing 4, wiersz 2.). KDialog pokazuje wpis Pliki MP3 w liście wyboru typów plików (Rysunek 5); jeśli rezygnujemy z opisu, wyświetla się samo rozszerzenie.
Rysunek 5: Jeśli chcemy, by skrypt pracował tylko na plikach dźwiękowych, powinniśmy ograniczyć możliwość wyboru użytkownika.
Po opcji --getopenfilename po prostu podajemy ścieżkę, na której okno dialogowe ma się ustawić – w tym przykładzie był to obecny katalog roboczy. Jeżeli zmienimy ten wpis na :label1, menedżer plików ustawi się na miejsce, w którym był pozostawiony poprzednio, czyli w ostatnio używanym folderze.
Listing 4: Otwieranie konkretnych typów plików
kdialog --passivepopup "To nie było konieczne..." 5 kdialog --getopenfilename . " *.mp3 | Pliki MP3"
Podsumowanie
Jeżeli piszemy skrypty dla innych użytkowników, okna dialogowe dają im przydatne graficzne wsparcie – szczególnie gdy są nowymi użytkownikami. Na koniec małe ostrzeżenie: nie dziwmy się, jeśli będziemy przepisywać skrypty, z którymi pracujemy, gdyż łatwo przyzwyczaimy się do komfortu, jaki daje wsparcie graficzne.
Informacje
[1] Manual Zenity
[2] Manual KDialog
very nice,
sam właśnie się przymierzałem do napisania arta o zenity w takim kontekście jak to
sprawa ma sie tak, ze zarowno zenity jak i kdialogs dosc ociezale startuja
a ja dorzucę swoje czy grosze – w konsoli można uzyskać takie efekty wykorzystując „dialog”