Program GIMP i polowanie na brakujące ikonki
W tym wpisie pobocznym (spoza strony głównej) opiszę historię rozwiązania problemu kilku brakujących ikonek w programie GIMP, służącym do obróbki grafiki. Pokażę krok po kroku, jak dzięki odrobinie dedukcji i prostych poleceń konsolowych udało się dojść do źródła błędu.
Opis może się przydać osobom chcącym zobaczyć trochę majsterkowania w praktyce i może kiedyś samodzielnie rozwiązywać problemy z Linuksami.
Zapraszam, znajomość programowania zbędna ![]()
Spis treści
Trochę kontekstu
Od kilku miesięcy dość często korzystam z systemu PorteuX, opartego na Linuksie. Cenię go przede wszystkim za ulotność, czyli fakt, że po każdym włączeniu ładuje się od zera (ale błyskawicznie), z pendrive’a.
Dzięki temu nie mam obaw, że coś sobie trwale popsuję w systemie podczas eksperymentów. Poza tym zyskuję sporo prywatności, bo na komputerze nie gromadzą się pliki osobiste ani charakterystyczne. A przynajmniej nie przez czas dłuższy niż jedna posiadówka.
PorteuX ma jednak pewne bariery wejścia. Jedną z nich jest nietypowa forma instalowania programów zewnętrznych – ładuje się je z plików XZM, zaś ich domyślnym źródłem są bazy Slackware’a.
Działa to sprawnie od strony technicznej, nie mówię że nie. Ale w porównaniu z popularniejszymi sposobami instalowania, ten niestety jest dość słabo opisany i obgadany na forach. Jeśli któryś program od Slackware’a nie do końca działa, to jestem zwykle zdany na siebie.
Tak było również w przypadku Gimpa, czyli popularnego programu do edycji grafiki. Moduł dostępny w domyślnej bazie (getpkg -m gimp) nie działał i musiałem zdobyć jeszcze trochę zależności, czyli programów i bibliotek niezbędnych do jego uruchomienia. W końcu się to udało, ale to temat na osobną opowieść.
W każdym razie, kiedy już doszedłem do etapu, gdy Gimp się włączał i śmigał, pozostały kwestie kosmetyczne. Nie wyświetlały mi się niektóre ikonki, jak te w narzędziu do edycji tekstu. Różne przekształcenia (pogrubienie, kursywa…) nie miały własnych oznaczeń graficznych, tylko ikony zastępcze:

Przy tym powiększeniu niezbyt to widać, ale na ikonkach zastępczych widnieje Wilber (maskotka Gimpa) ze styraną miną.
Metoda rozwiązywania błędów, która dotąd się przy Gimpie sprawdzała – czytanie komunikatów konsolowych, w których wprost ostrzegał o brakach – w tym wypadku nie pomagała. Nie było żadnych komunikatów.
Przyznam, że nie rozwiązałem problemu od strzała, brakło mi cierpliwości. Zamiast tego co parę tygodni do niego wracałem i poświęcałem do pół godziny na wypróbowanie czegoś, co przyszło do głowy. W końcu się udało.
Nieudane próby
Wcześniej korzystałem ze świetnego programu strace, pozwalającego monitorować wszystkie interakcje wskazanego programu z systemem plików.
Dokładniej rzecz biorąc, po zainstalowaniu świeżego Gimpa używałem takiej komendy konsolowej.
strace -o gimp-zapiski.txt -f -yy -s 1 gimp
Przyjmę tu taką konwencję: komendy konsolowe będą tekstem takim jak wyżej, jaśniejszym. Tekst wyświetlany w konsoli albo innych programach będzie ciemniejszy. Fragmenty interesujące będę w paru miejscach wyróżniał dodatkowymi kolorami.
Omówienie komendy
Na początku jest nazwa samego programu, strace. Cała reszta to wrzucane do niego parametry o następujących efektach:
-
-o PLIKzapisuje wyniki monitorowania do konkretnego pliku, w tym wypadkugimp-zapiski.txt, -
-fkaże monitorować również podprocesy aktywowane przez ten śledzony, -
-yykaże zapisywać pełne nazwy i ścieżki plików (kluczowe!), -
-s 1ogranicza do minimum podgląd rzeczy zapisywanych lub odczytywanych (znaczna oszczędność miejsca w tworzonym pliku), -
gimpto komenda, pod którą podpinam śledzenie, po prostu uruchamiająca Gimpa w domyślnym trybie działania.
Niestety, jak zobaczymy, Gimp nie ładował ikon w sposób najprostszy i bezpośredni. Droga przez strace’a – choć nieraz sprawdzona, również przy innych dziwactwach Gimpa – tym razem nie doprowadziła mnie do celu.
Oczekiwania kontra rzeczywistość
Liczyłem na to, że w zapiskach strace’a trafię z grubsza na taki komunikat o nieudanym wczytaniu pliku z ikoną:
W ten sposób jasno bym widział: Gimp próbował odczytać ikonę, ale jej nie znalazł i zrezygnował. Miałbym nazwę brakującego pliku, której mógłbym poszukać w internecie.
Niestety ta eksploracja mnie donikąd nie doprowadziła; przy ikonach zdarzało się nieraz, że Gimp nie znalazł pliku w jednym miejscu, ale chwilę potem sprawdził w kolejnym i już go wczytał. Musiałbym odsiać takie przypadki, żeby zostać wyłącznie z zapiskami dotyczącymi wczytania całkiem nieudanego.
Poza tym nie wiedziałem nawet, pod jakimi nazwami wypatrywać brakujących plików, ani czy w ogóle są w wynikach strace’a (Gimp mógł pytać o pliki jakiegoś procesu systemowego, który nie był monitorowany).
Rozwiązanie problemu
Podczas jednej ze wspomnianych szybkich prób ugryzienia problemu zrobiłem wreszcie dwie rzeczy, które okazały się kluczem do rozwiązania zagadki.
-
Pobrałem kod źródłowy Gimpa.
-
Najechałem kursorem na brakującą ikonę.
Rzecz pierwsza jest dość oczywista, druga nieco mniej.
Chodzi o to, że po najechaniu kursorem wyświetla się pomocniczy opis wskazywanego elementu. W ten sposób poznałem tekst przypisany do jednego z przycisków bez ikony.

Punkt zaczepienia: tekst elementu
Strikethrough, czyli przekreślenie. Nie wyglądało to na szukaną nazwę ikony… Ale mogłem mieć podejrzenie, że w kodzie Gimpa tekst i ikona pojawią się gdzieś blisko siebie.
Mając folder z kodem źródłowym, wszedłem do jego wnętrza i użyłem linuksowego „przeszukiwacza wnętrza plików”, Grepa:
grep -r "Strikethrough"
Argument -r sprawia, że Grep przeszukuje wszystkie pliki i podfoldery (oraz ich podfoldery itd.) w miejscu, w którym odpaliłem komendę.
W konsoli wyskoczyło całkiem sporo linijek! Miały ogólny format:
Wiele tych plików miało końcówkę .po. To popularny format, zawierający tłumaczenia tekstu. Nic dziwnego, że się pojawiły; w końcu szukałem słowa widocznego dla użytkowników, a Gimpa przełożono na wiele języków.
Wspólną cechą plików z tłumaczeniami była ścieżka zaczynająca się od po/. A to pozwoliło łatwo je odsiać, gdy dodałem do pierwszego Grepa filtrowanie:
grep -r "Strikethrough" | grep -v "po/"
Po filtrowaniu pozostał tylko jeden pasujący wynik. Pomijając dla czytelności wielokrotne spacje:
app/widgets/gimptextstyleeditor.c: _("Strikethrough"));
Kolorem wyróżniłem ścieżkę do pliku. Miał w nazwie text style editor, czyli brzmiał dokładnie jak to, czego szukałem!
Co jeszcze mówiła mi nazwa? Końcówka pliku .c sugerowała, że to kod źródłowy napisany w języku C. Którego nie znam… Ale mogłem mieć nadzieję, że będzie na tyle intuicyjny, że się połapię.
Plik z kodem edytora tekstu
Znaleziony plik mogłem sobie otworzyć w czymkolwiek, wybrałem domyślny notatnik.
Wyszukałem w pliku słowo Strikethrough i zobaczyłem, że cały blok kodu, zapewne odpowiedzialny za stworzenie przycisku, wyglądał tak:
gimp_text_style_editor_create_toggle (editor, editor->buffer->strikethrough_tag,
GIMP_ICON_FORMAT_TEXT_STRIKETHROUGH,
_("Strikethrough"));
Jeśli czytasz na urządzeniu mobilnym, to dolne linijki mogą nie zmieścić się na szerokość. Można wtedy przewinąć pole w poziomie.
Wokół było więcej podobnych bloków kodu, odpowiadających innym przyciskom edytora. Co najcenniejsze: miałem tu zmienną GIMP_ICON_FORMAT_TEXT_STRIKETHROUGH. Miała w tekście ICON – mocna przesłanka za tym, że to tego szukałem!
Było to również jedyne wystąpienie tej zmiennej w pliku. A zmienne nie biorą się znikąd, muszą być gdzieś zdefiniowane.
Logiczny wniosek? Ta zmienna musiała powstawać w innym pliku, zaś w to miejsce była ładowana podczas działania programu.
Za jej załadowanie odpowiadała zapewne któraś z linijek zaczynających się od #include i umieszczonych na początku pliku (podział kodu na moduły, podstawa programowania).
Było tych plików sporo, więc nie odwiedzałem ich po kolei, tylko zrobiłem kolejne przeszukiwanie masowe, wśród wszystkich plików źródłowych:
grep -r GIMP_ICON_FORMAT_TEXT_STRIKETHROUGH
Poza wiadomym wystąpieniem w pliku, w którym właśnie byłem, znalazło tylko jedno (kolorem wyróżniłem nazwę pliku):
libgimpwidgets/gimpicons.h:#define GIMP_ICON_FORMAT_TEXT_STRIKETHROUGH "format-text-strikethrough"
Plik z definicjami ikonek
Nazwa znalezionego pliku zawierała tekst gimp icons, więc ponownie brzmiała obiecująco. Swoją drogą – pliki .h również sugerują język programowania C.
Odwiedziłem go i istotnie była tam linijka, w której miało miejsce stworzenie interesującej mnie zmiennej:
Miałem tutaj przypisanie do zmiennej (po lewej) ciągu znaków (po prawej, otoczonego cudzysłowami) format-text-strikethrough.
Skopiowałem ten tekst i zrobiłem kolejne pełne przeszukanie kodu. Ale nie występował nigdzie poza plikiem gimpicons.h.
Połączyłem to z faktem, że zmienna, do której został przypisany ten tekst, też nie była rozsiana po plikach; trafiała prosto do kodu tworzącego przycisk.
Było zatem bardzo możliwe, że tekst był początkiem całej drogi – oczekiwaną nazwą ikony. Gdzieś musiała być określona, a to miejsce pasowało.
Swoją drogą w kodzie miałem więcej linijek przypisujących tekst do zmiennych. Niektóre pasowały do innych przycisków, które mi się nie pokazywały.
Strace ślepym zaułkiem – potwierdzenie
Wspomniałem na początku, że programik strace mi tym razem nie pomógł, bo nie zaobserwowałem nietypowych błędów w ładowaniu ikon.
Teraz, mając konkretne nazwy plików, mogłem się upewnić, że nie było to przeoczenie. Użyłem tego polecenia co wcześniej, a potem przeszukałem zapiski pod kątem znalezionych nazw (jak np. format-text-bold).
Niczego nie znalazło, nawet nieudanych prób otwarcia. Utwierdziło mnie to w przekonaniu, że za ładowanie czcionek odpowiadał jakiś inny proces, niepodpięty pod Gimpa. A strace w tym trybie, w jakim go używałem, nic by nie pomógł.
Ustalenie folderu na ikonki
Na tym etapie miałem wystarczająco wiele informacji i charakterystycznych nazw, żeby spróbować poszukać w internecie brakujących ikon. Uruchomiłem wyszukiwarkę.
Po szukaniu pod hasłami pokroju "format-text-bold" gimp icons wyskoczyło mi parę stron z fragmentami kodu, które właśnie przed chwilą odkryłem… a także konkretna ikona w formacie wektorowym SVG.
Sam projekt, którego ta ikona była częścią, wydaje się nieoficjalnym motywem graficznym; personalizującym Gimpa, żeby przypominał program Blender.
Mógłbym po prostu użyć tych ikon, gdyby zależało mi jedynie na uzupełnieniu braków. Ale to nie było dokładnie to, czego używał oficjalny Gimp.
Oprócz ikon projekt zawierał również opis ich instalowania, który naprowadził mnie na dobry trop. Była tam bowiem informacja o tym, co należy wyklikać w Gimpie, żeby poznać ścieżki do folderów na ikony.
U mnie (Gimp 3.0.6) rzeczy do przeklikania były inne, ale zbliżone:
Edit > Preferences > Icon Theme
Był tam aktywny motyw (domyślny, Default) oraz jego ścieżka:

Odwiedziłem ten folder. Wewnątrz było kilka innych podfolderów; pełna ścieżka do tego, z którego Gimp brał ikony, okazała się taka:
/usr/share/gimp/3.0/icons/Default/scalable/apps
W tym konkretnym miejscu już mógłby się przydać strace – pozwoliłby potwierdzić, że Gimp bierze działające ikony z tego folderu.
Brakujących ikon z narzędzia tekstowego tu nie było, zero zaskoczenia. Mogłem natomiast przyjrzeć się ikonom działającym. Nie wiedziałem, czy wyłapię cokolwiek ciekawego, to była eksploracja.
Porównując nazwy ikonek z pliku gimpicons.h z plikami obecnymi w tym miejscu, zauważyłem parę różnic:
- ikonki kończyły się na
.svg, - wiele z nich miało w nazwie
-symbolic.
Założyłem na tej podstawie, że w pliku z definicjami są same trzony, zaś nazwa pliku jest tworzona według szablonu: {trzon}-symbolic.svg.
Przeszukanie całego systemu
Znałem już pełne, oczekiwane nazwy ikon. Wiedziałem, w jakim folderze je umieścić. Pozostaje tylko pytanie – skąd je zdobyć?
Na tym etapie miałem kilka pomysłów, ale najpierw postanowiłem sprawdzić, czy takie ikony nie trafiły mi omyłkowo do jakiegoś innego podfolderu Gimpa. Zarzuciłem sieć szeroko, robiąc przeszukanie nazw plików z całego systemu:
sudo updatedb
locate "format-text-bold-symbolic"
Mocno się zdziwiłem, kiedy znalazło mi taki plik nie wewnątrz Gimpa, tylko w plikach systemowego motywu graficznego:
/usr/share/icons/elementary-xfce/actions/symbolic/format-text-bold-symbolic.svg
A czemu Gimp tutaj nie sięgał? Czy z założenia nigdy tego nie robił, czy też z moim motywem było coś nie tak?
Tego niestety nie ustaliłem. Miałem natomiast mocne przeczucie, jak rozwiązać problem z ikonami.
Ślepy zaułek – nagłówek pliku
Na tym etapie przyszło mi do głowy, że pliki SVG z motywu systemowego mogły być ignorowane, bo nie zawierały w pierwszej linijce nagłówka wskazującego typ pliku:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
Wszystkie ikony z wnętrza Gimpa go miały, te z motywu systemowego już nie.
Ostatecznie nie okazało się to źródłem problemu, a ikony skopiowane do folderu Gimpa działały również bez nagłówka.
Warto jednak pamiętać, że nagłówki też bywają kłopotliwe – przykładowo program Graphviz nie ładuje podlinkowanych plików, jeśli są ich pozbawione.
Kopiowanie ikon do folderu Gimpa
Mogłem teraz odczytać nazwy ikon z pliku gimpicons.h, znaleźć ich odpowiedniki w plikach systemowych i skopiować je do folderu Gimpa. A potem zobaczyć, czy teraz Gimp je znajdzie.
Nie chciałem jednak robić tego na oko, bo istniało ryzyko, że naprawię tylko ikony dotąd znalezione, a pominę inne braki. Żeby rozwiązać to w sposób automatyczny i pełniejszy, stworzyłem skrypt pomocniczy w języku Python, który:
- zagląda do pliku
gimpicons.hz kodu źródłowego
(musi być pobrany i wypakowany, domyślnie w tym folderze co skrypt), - kopiuje stamtąd trzony nazw ikon i tworzy z nich pełne nazwy według szablonu,
- sprawdza, czy ma takie pliki w folderze z domyślnymi ikonami zainstalowanego Gimpa,
- jeśli nie, to szuka plików o takich nazwach w folderach systemowych,
- jeśli znajdzie pasujące ikony, to je kopiuje do folderu Gimpa.
Efekt działań? Do folderu Gimpa trafiało kilkanaście systemowych ikon. Zaś narzędzie od tekstu, podobnie jak parę innych elementów, stawało się czytelne:

…Czy to rozwiązało wszystkie problemy? Niestety nie – nadal nie pokazuje mi się kilka ikon wewnątrz okna zapisu/eksportu plików.
Mam podejrzenie, że to już jakiś problem ogólny, związany ze szkieletem GTK, na którym opiera się Gimp i niejedna inna aplikacja. To jednak sprawa na osobną przygodę.
Mam nadzieję, że wpis pokazał coś nowego albo przynajmniej użytecznego. Po kolejne zapraszam na stronę główną ![]()
Bonus: stworzenie pakietu instalacyjnego
W obecnej sytuacji byłem zdany na skrypt Pythona, kopiujący brakujące ikony w oczekiwane miejsce (przypomnę: mój system celowo resetuje swój stan po każdym wyłączeniu, więc nie wystarczy, że skopiuję je tylko raz).
Co zrobić, żeby to uprościć i zyskać Gimpa, który po najprostszej instalacji już ma wszystkie ikony? Mogłem stworzyć sobie przenośny instalator. Coś, co po kliknięciu albo aktywacji programem umieszcza ikonki tam, gdzie powinny być.
Tworzenie instalatora na systemie PorteuX
W skrypcie ustawiłem (wpisując ścieżkę w zmienną CUSTOM_ICON_COPIES_FOLDER), żeby skopiowało mi brakujące ikony nie do folderu Gimpa, tylko do innego, który nazwałem gicons. Wybór nazwy czysto subiektywny.
Następnie uruchomiłem konsolę i stworzyłem sobie ścieżkę – na razie tylko jako zmienną – której pierwszy człon nazwałem gimp-missing-icons (też wedle kaprysu). Jej dalsza część (wyróżniona) była identyczna jak pełna ścieżka do folderu na ikony Gimpa:
iconpath=gimp-missing-icons/usr/share/gimp/3.0/icons/Default/scalable/apps
Następnie stworzyłem wszystkie foldery składające się na tę ścieżkę:
mkdir -p $iconpath
A potem skopiowałem tam ikony z folderu tymczasowego gicons:
cp gicons/*.svg $iconpath
W ten sposób miałem małe drzewko folderów, które po nałożeniu na moje główne, systemowe, „włożyłoby liście” (pliki SVG) prosto do folderu Gimpa. Tam, gdzie ten ich domyślnie wypatruje.
Pozostało spakować to równoległe drzewko w moduł XZM. Tym razem musiałem odwołać się do folderu na początku całej ścieżki:
dir2xzm gimp-missing-icons
Efektem komendy był plik gimp-missing-icons.xzm, zawierający pełne „drzewko uzupełniające” plików i folderów, do nałożenia na główny system plików.
Mogłem go sobie teraz umieścić na pendrivie i aktywować razem z pozostałymi modułami związanymi z Gimpem. Gdybym chciał, mógłbym również go scalić z modułem głównym Gimpa:
mergexzm {moduł_główny}.xzm gimp-missing-icons.xzm
W ten sposób miałbym wszystko upakowane w jednym samowystarczalnym pliku.