mirror of
https://codeberg.org/postscriptum/devzone.org.ua.git
synced 2026-02-19 22:12:39 +00:00
99 lines
No EOL
21 KiB
Markdown
99 lines
No EOL
21 KiB
Markdown
# Мої перші кроки в GTK
|
||
|
||
## Передмова
|
||
|
||
Не так давно захотілось зробити простенький браузер для [протоколу Gemini](https://devzone.org.ua/tag/gemini). Зокрема - додати детекцію Geo-IP капсул, власний пошук на базі [Manticore](https://devzone.org.ua/tag/manticore) та інтегрувати екосистему [Yggdrasil](https://devzone.org.ua/tag/yggdrasil).
|
||
Для обраного протоколу задача виглядала тривіальною, залишалось обрати графічний фреймворк і накидати туди крутих функцій.
|
||
|
||
Я постійний користувач Linux, вибір був між Qt та GTK. З Qt вже поверхнево знайомий, в рамках одного з проектів, що довелось апгрейдити і разом з тим оновлювати залежності API (досі приходить спам після обов'язкової реєстрації для завантаження останньої SDK)
|
||
Але оскільки завжди був користувачем середовища GNOME, все таки пішов стежкою GNU і вирішив глянути що там і як робиться на практиці.
|
||
|
||
Забігаючи вперед, скажу що займався професійно виключно веб розробкою, добре знаю суміжні мови, патерни і фреймворки. Але це була фактично моя перша десктоп програма, яку захотілось написати з нуля.
|
||
Заради цікавості вбив у пошук знайому для себе комбінацію "PHP-GTK" і щось там побачив! Ну, а оскільки вже чимало часу провів з PHP, то написати браузер цією мовою було доволі простою задачею - в запасі вже було з десяток власних бібліотек, лишалось їх тільки натягнути на віконний API і все.
|
||
|
||
Отже, знайшов пару прикладів, написав простенький код виклику вікна - працює, значить працюватиме й інше!
|
||
|
||
## Інформація в мережі
|
||
|
||
Перше з чим зіткнувся, на відміну від Qt, PHP/JS та інших поп-технологій, пошукові видачі по GTK - порівняно порожні або посилаються на якісь старі мануали по другій версії.
|
||
|
||
Звісно є [офіційна документація](https://docs.gtk.org), але без розуміння загальної картини.. взагалі складно.. як, що, до чого. На ютубі теж тотальний кошмар, але частково є англомовний контент в основному по двійці, якості не краще. Краще не дивитись. Довелось пробиратись через тернові хащі розуміння самому. Вирішив нарешті задати дільне питання Chat GPT і Haiku, останній до речі доволі точно і лаконічно генерує приклади на Python, C та C++
|
||
|
||
## Документація
|
||
|
||
В принципі, вона є але доволі скупа і потребує деякого рівня для входу. Але так якщо писати програму по інструкціям ШІ та паралельно читати документацію по кожному методу і його типам то по-трохи можна в'їхати що до чого.
|
||
|
||
## Поняття Widget
|
||
|
||
В якийсь момент, почав розуміти що є деякі класи, з яких подібно блокам конструктора, складається вікно і всі його елементи. Ці класи потрібно зібрати до купи в рамках іншого класу-віджету у потрібному порядку і вкладеності: копки, поля та інше - формуючи в результаті вікно і заголовок (який тут теж є віджетом).
|
||
|
||
Згодом, працюючи безпосередньо з компонуванням, стало відомо про такий інструмент як Glade, який дозволяє робити те само не в коді а через UI (як Unity для ігор) а проект експортувати - в XML, який в свою чергу, потім можна імпортувати в об'єкти - вже засобами класу [Builder](https://docs.gtk.org/gtk4/class.Builder.html).
|
||
|
||
В принципі, використовувати Glade чи ні - справа вподобань. Особисто мені не подобається UI та XML як явище в ООП, але офіційного аналогу JSON не знайшов, тому й далі описую віджети об'єктами в коді програми. Варто зазначити, що для GTK 4, Glade вже не використовується, а на його офіційному сайті висить [заглушка nginx](https://glade.gnome.org). Тут на зміну для четвірки приходить нова і мабуть єдина, неофіційна програма і новий формат проекту файлів - [Cambalache](https://gitlab.gnome.org/jpu/cambalache).
|
||
|
||
## Ієрархія і наслідування
|
||
|
||
Через певний час роботи, виявиться що деяких методів в прикладах, які описує ШІ немає в документації класу і це не помилка! Як виявляється, на сторінці кожного віджету можна побачити [дерево наслідування](https://docs.gtk.org/gtk4/class.Box.html#hierarchy), і воно там проілюстроване не спроста
|
||
|
||

|
||
|
||
Таким чином, в пошуках певної функції для тюнінгу програми, вже можна читати не тільки документацію робочого класу, але й обов'язково його батьківського елементу - де виявляється ціла купа нових методів про які на сторінці самого методу не згадується окрім клікабельної мапи наслідування. Це була суто моя, користувацька неуважність і як наслідок самостійна реалізація функціональності яка вже була давно доступна, просто з інструментами які знаходяться рівнем вище у батьківських класах та групах об'єктів.
|
||
|
||
Якщо пишете програму на C, то ймовірно це буде простіше, оскільки компілятор підсвітить та авто-доповнить семантику. Але в моєму випадку - був шлях пробивного першопрохідця на PHP, який ще й писав порт на PHP-CPP мабуть довше ніж сам браузер.
|
||
|
||
По цій темі можна ще додати наступне. Якщо ви пишете першу програму GTK на C++, то ймовірно вже віднайшли і користуєтесь враппером [gtkmm](https://gtkmm.org) (і його сателітами - glibmm і giomm) - така собі абстракція, яка спростить код але добряче заплутає в офіційній документації для C через свою абстрагованість. Частина API в gtkmm досі не реалізована. Також офіційні класи GTK 4, на відміну від GTK 3, вже оголошені як final, тобто не можуть наслідуватись і передбачають або агрегацію або композицію. Разом з тим, gtkmm все ще дозволяє наслідування (подібно Qt) і тут звісно теж не дуже зрозуміло як краще проектувати програму згідно стандартам і що на gtkmm чекатиме завтра. Але бібліотека безумовно зручна, дійсно зменшує об'єм коду в рази три.
|
||
|
||
Все таки мені здається оптимальним писати першу програму GTK на С а не C++, чи наприклад Rust. C, не зважаючи на потенційно більшу кількість коду і відсутність ООП, на мою думку, буде простішим шляхом для початківця, зокрема у вивченні того як влаштована ієрархія фреймворку, події, використання пам'яті. І вже тільки потім варто переходити на абстрактний рівень вище. Для себе все ще не визначився бо все життя провів в ООП, і вже не уявляю без цього програму більшу за "hello world"
|
||
|
||
## Типи даних і допоміжні функції
|
||
|
||
Низькорівневі бібліотеки [Gio](https://docs.gtk.org/gio)/[Glib](https://docs.gtk.org/glib) містять чимало зручних функцій для роботи з кодуванням, розміткою, сокетами і взагалі все що потрібно для роботи з контентом. Багато з них наслідують STL. Коли я вперше відкрив для себе розділ функцій то чомусь мені згадалось різноманіття препроцесору розмітки PHP - де є все для роботи з веб, а у веб зараз є все.
|
||
|
||
Таким чином, майже не використовую STL бо майже на кожну функцію і тип даних, в середовищі GTK для них є розширена і адаптована реалізація.
|
||
|
||
## Робота з контентом
|
||
|
||
Якщо говорити про вивід даних в контексті браузеру, який у моєму випадку має відображати простий gemtext з клікабельними посиланнями, починається деякий дисонанс після роботи з JS/HTML.
|
||
|
||
По-перше в GTK є тільки два відомих мені віджети для тексту - [Label](https://docs.gtk.org/gtk4/class.Label.html) і [TextView](https://docs.gtk.org/gtk4/class.TextView.html)
|
||
|
||
`Label` - це по суті блок для невеликого тексту, який може підтримувати розмітку або звичайний текст. Розмітка при цьому використовує формат [Pango](https://docs.gtk.org/Pango), тобто це такий собі мінімальний варіант HTML з декількома тегами і класами, що використовується для інших, специфічних для стаціонарних програм цілей. Поле `Label` не розраховане на великий об'єм даних, тому як і варто очікувати мігрантам з HTML - сенс його однозначний - невеличкий опис до якогось блоку і все. Текст на 100Кб відправить вашу програму в роздуми на 10 секунд, особливо якщо спробуєте відформатувати [Layout](https://docs.gtk.org/Pango/class.Layout.html) своїм способом, наприклад перерахувати word-wrap чи відмалювати інакше шрифти перед додаванням у віджет.
|
||
|
||
Тим не менше, усі дороги і поради "бувалих" ведуть саме на `Label`, але якщо залізти у вихідний код інших, швидких GTK браузерів то побачимо, що часто використовується багаторядкове текстове поле вводу `TextView`. По суті, це аналог поля `textarea`, в якому достатньо сховати курсор засобами CSS (наприклад, через `caret-color: transparent`) та перевести віджет в режим [readonly](https://docs.gtk.org/gtk4/method.Editable.set_editable.html).
|
||
Цей віджет так само підтримує розмітку, події, користувацькі теги а також буфер, в який можна складати і відмальовувати невеликий текст по мірі прокрутки контенту, як багато хто і робить що і являє собою розгадку швидкодії рендерингу великих документів.
|
||
|
||
Говорячи про прокрутку. Ще не знаю як в GTK 4, але в GTK 3 віджет, який не підтримує засоби скролу, потрібно додати у відповідний контейнер [Viewport](https://docs.gtk.org/gtk3/class.Viewport.html). Інакше ви довго не будете розуміти чому ваш текст сам по собі відскролюється на верх, наприклад при перемиканні табів `Label` віджету `Notebook`. Так само в іншому, очевидно вектор спрощення торкається не тільки візуальної але і внутрішньої частини GTK - розробник повинен сам реалізувати потрібні йому набори, навіть якщо вони здаються тривіальними і такими, що здавалось би, мають бути з коробки.
|
||
|
||
Щодо CSS - тут від нього тільки три літери, і мабуть три властивості в залежності від двох тегів, які оберете :)
|
||
|
||
Є віджет для картинки ([Picture](https://docs.gtk.org/gtk4/class.Picture.html)) і є для більш простої піктограми, наприклад для віджету кнопки ([Image](https://docs.gtk.org/gtk4/class.Image.html)) якщо треба більше - пишіть самі. Мінімалізм.
|
||
|
||
## Робота з діями
|
||
|
||
Фреймворк базується на системі подій, тому, хто добре знайомий з JavaScript / Node.js, буде просто розібратись.
|
||
Кожен віджет здатен оголошувати власні [Action](https://docs.gtk.org/gtk4/actions.html), [ActionGroup](https://docs.gtk.org/gio/iface.ActionGroup.html), а також звертатись до глобальних рівнів вікна (`win`) та застосунку (`app`)
|
||
|
||
Взагалі тема велика і було б добре написати про неї окремо, але нагадаю, особливо бекендерам: на систему дій потрібно звернути увагу в першу чергу і не писати передачу викликів методами класів, ін'єкцією залежностей і т.д., як робив це я спочатку.
|
||
|
||
## Спільнота
|
||
|
||
В GNU спілньота живе десь в чистилищах своїх гітлабів та інших екзотичних місцях. На гітхабі звісно ваша присутність не допоможе, доведеться по всім баг-репортам реєструватись на окремих сайтах. А для підтримки користуватись [форумом](https://discourse.gnome.org/). В принципі 2-3 користувача час від часу відповідають (схоже на співробітників фундації) але особисто мені це не зовсім зручно, в порівнянні з системою Issues та PR на GitHub.
|
||
|
||
Для себе, в навчанні, й досі користуюсь ШІ, потім читаю документацію, пишу код, і так по колу. Пошук Google тут видає аж нічого цікавого. В принципі форум читати не дуже інформативно бо старі теми там закриваються і коментувати туди вже не можна.
|
||
|
||
## Висновки
|
||
|
||
Мені чимось подобається графічне середовище GNOME: можливо своєю простотою та однорідністю застосунків, що схоже за філософією на MacOS, користувачем і фаном якої я був довгий час. Й досі, використовую GOME на машині iMac (оскільки для розробки користуюсь Linux)
|
||
|
||
GTK має більш інтуїтивний, матеріальний інтерфейс, в той час як Qt та різноманітні JS/Electron чомусь асоціюються з пластиком, де кожна програма має різні властивості, таймінги відгуку, що не зручно коли фокусуєшся на роботі.
|
||
|
||
Звісно з трійкою все пішло мобільним шляхом, робочий стіл став пустим місцем, а програми такі прості що виконують буквально одну функцію. Все що більш менш в побуті - на Qt.
|
||
|
||
Власне кажучи, буду намагатись й надалі в'їхати в тему GTK, а коли все вляжеться і засвоїться то може буде сенс написати якийсь навчальний матеріал по одній конкретній темі. Ну а зараз, думаю краще поділитись тим що маю - першим враженням з точки зору розробника, і як бачу GTK під капотом в цілому після декількох місяців користування.
|
||
|
||
Щодо браузера - наразі в нього утворилось дві гілки:
|
||
|
||
* [PHP-GTK3](https://github.com/YGGverse/Yoda/tree/PHP-GTK3) - більш функціональна але ймовірно вже архівна версія, оскільки писати на GTK 3 не бачу сенсу а вкладатись в контрибуцію бібліотеки Zend / GTK 4 зараз не цікаво. По суті включає базові функції - відкриває файли, протоколи [nex](https://devzone.org.ua/post/protokol-nex-lehka-alternatyva-gemini) та gemini. Останньою фічею була авторизація сертифікатами TLS (коди групи 60), тому якщо комусь цікаво - може поколупатись в робочих прикладах багатопоточної реалізації PHP/GTK так і обробки протоколу Gemini зокрема.
|
||
* [CPP-GTK4](https://github.com/YGGverse/Yoda/tree/CPP-GTK4) - остання версія, стан чернетки, в якій я досі не визначився з патерном. Можливо взагалі переключусь на C або відкрию нову гілку на Rust, який мене давно цікавить своїм пакетним менеджером.
|
||
|
||
Поки що все, діліться вашим досвідом знайомства з GTK, якщо такий є ;) |